Introduction

Washington University Medical Center Redevelopment Corporation is a partnership between BJC Health Care and Washington University School of Medicine and works to improve the quality of life for the neighborhoods surrounding the medical campus. In order to achieve this goal in Forest Park Southeast and the Central West End , WUMCRC has invested millions of dollars toward regenerating the market for private investment in businesses and real estate, enhancing human and social service opportunities, and improving the level of physical and personal security.

One way we work to improve the level of physical & personal security is the analysis and distribution of data. The original source of this crime data is http://slmpd.org/crimereports.shtml. This notebook uses primarily compstatr to access and clean the crime data.

R Markdown

Tidy data

Create an Index

i <- cs_create_index()

Get Data - 2019

update <- cs_last_update()
update <- strsplit(update, " ")[[1]]
c_month <- update[[1]]
c_year <- as.numeric(update[[2]])
yearList19 <- cs_get_data(year = c_year, index = i)

Download Current Month

cs_validate(yearList19, year = 2019)
[1] TRUE
totalCrimes19 <- cs_collapse(yearList19)
print(c_month)
[1] "August"
crimes19 <- cs_extract_month(yearList19, month = "August") 

Clean & Categorize Data - 2019

cs_filter_count removes negative counts. Negative counts, -1, in the count column means that the crime, or charge in this specific observation has either been deemed unfounded, or the crime has been up coded. We do not want to map this data.

Many of the analyses we conduct include comparisons between violent & non-violent crime, comparisons on the amount of crimes happening in each crime cateogy over time, and if crimes occur during the day or at night. The following code ceates variables to conduct these analyses.

cs_crime_cat creates a variable with the names of the crime.

cs_crime creates a logic variable and codes violent crimes as TRUE and non-violent crimes as FALSE

cs_parse_date creates two columns separating the Date Occur variable. The two colums are as follows: one contains the date - month, date, and year, and the other contains the hour and minute. This is used because crimes coded in the most recent month, can contain dates that occured, in previous months or years & in this report we only want to map the crimes that occured in the past month.

filter is a dplyr function that filters out any dates that occur before the our selected date, and also filters out crimes that did not happen in either District 2 or district 5.

mutate adds a variable that codes and labels the days of the week for each crime that occurred, and creates another time of day variable

tidyCrimes19 <- crimes19 %>% 
  cs_filter_count(., var = count) %>%
  cs_filter_crime(., var = crime, "part 1") %>%
  cs_crime_cat(., var = crime, crimeCatNum, "numeric") %>%
  cs_crime_cat(., var = crime, crimeCatName, "string") %>%
  cs_crime(., var = crime, violent, "violent") %>%
  cs_crime(., var = crime, property, "property") %>%
  cs_parse_date(., date_occur, dateVar = dateOcc, timeVar = timeOcc) %>%
  filter(dateOcc >= as.Date("2019-08-01")) %>%
  filter(district == 2 | district == 5) %>%
  mutate(weekday = wday(dateOcc, label = TRUE)) %>%
  mutate(tod = timeOcc)

tidyCrimes19$neighborhood <- as.numeric(tidyCrimes19$neighborhood)

strptime and format takes the new time variable and formats it to a character so that we can determine if the crime occured at day or at night, and creates a second coded variable that labels each observations as day or night based on the newly formated time variable.

select drops the unneeded variables.

cs_missing_XY determines what data does not have x & y coordinates, and therefore cannot be accurately mapped.

cs_replace0 replaces missing x & y coordinates with NA, and drops the missing data.

tidyCrimes19$tod <- strptime(tidyCrimes19$tod, tz = "America/Chicago", "%H:%M")
tidyCrimes19$tod <- format(tidyCrimes19$tod, format = "%H%M%S")

tidyCrimes19 <- tidyCrimes19 %>%
  mutate(., dayNight = ifelse(tod >= "180000" & tod < "600000", "Night", "Day")) %>% 
  dplyr::select(-dateTime, -tod, -flag_crime, -flag_administrative, -flag_unfounded, -flag_cleanup)

tidyCrimes19 <- cs_missingXY(tidyCrimes19, varX = x_coord, varY = y_coord, newVar = missing)
table(tidyCrimes19$missing)

FALSE  TRUE 
  735     4 
tidyCrimes19 <- tidyCrimes19 %>% 
  cs_replace0(., var = x_coord) %>%
  cs_replace0(., var = y_coord) %>% 
  filter(., missing == FALSE) 

Total Crimes 2019 - Clean

totalYearlyCrimes19 <- cs_collapse(yearList19)

tidyTotalCrimes19 <- totalYearlyCrimes19 %>% 
  cs_filter_count(., var = count) %>%
  cs_filter_crime(., var = crime, "part 1") %>%
  cs_crime_cat(., var = crime, crimeCatNum, "numeric") %>%
  cs_crime_cat(., var = crime, crimeCatName, "string") %>%
  cs_crime(., var = crime, violent, "violent") %>%
  cs_crime(., var = crime, property, "property") %>%
  cs_parse_month(., var = coded_month, yearVar = reportYear, month = monthVar) %>%
  cs_parse_date(., date_occur, dateVar = dateOcc, timeVar = timeOcc) %>%
  filter(district == 2 | district == 5) %>%
  mutate(weekday = wday(dateOcc, label = TRUE)) %>%
  mutate(tod = timeOcc) 

tidyTotalCrimes19$neighborhood <- as.numeric(tidyTotalCrimes19$neighborhood)

tidyTotalCrimes19$tod <- strptime(tidyTotalCrimes19$tod, tz = "America/Chicago", "%H:%M")
tidyTotalCrimes19$tod <- format(tidyTotalCrimes19$tod, format = "%H%M%S")

tidyTotalCrimes19 <- tidyTotalCrimes19 %>%
  mutate(., dayNight = ifelse(tod >= "180000" & tod < "600000", "Night", "Day")) %>% 
  dplyr::select(-dateTime, -tod, -flag_crime, -flag_administrative, -flag_unfounded, -flag_cleanup)

tidyTotalCrimes19 <- cs_missingXY(tidyTotalCrimes19, varX = x_coord, varY = y_coord, newVar = missing)
table(tidyTotalCrimes19$missing)

FALSE  TRUE 
 5236    87 
tidyTotalCrimes19 <- tidyTotalCrimes19 %>% 
  cs_replace0(., var = x_coord) %>%
  cs_replace0(., var = y_coord) %>% 
  filter(., missing == FALSE)

rm(totalCrimes18)
object 'totalCrimes18' not found

Get Data - 2018

yearList18 <- cs_get_data(year = 2018, index = i)

Data Preperation

cs_validate(yearList18, year = 2018)
[1] TRUE

Download Last Year’s Month

totalCrimes18 <- cs_collapse(yearList18)
monthCrimes18 <- cs_extract_month(yearList18, month = "August")
rm(yearList18)

Clean & Categorize Data - 2018

tidyMonthCrimes18 <- monthCrimes18 %>% 
  cs_filter_count(., var = count) %>%
  cs_filter_crime(., var = crime, "part 1") %>%
  cs_crime_cat(., var = crime, crimeCatNum, "numeric") %>%
  cs_crime_cat(., var = crime, crimeCatName, "string") %>%
  cs_crime(., var = crime, violent, "violent") %>%
  cs_crime(., var = crime, property, "property") %>%
  cs_parse_date(., date_occur, dateVar = dateOcc, timeVar = timeOcc) %>%
  filter(dateOcc >= as.Date("2018-08-01") & dateOcc <= as.Date("2018-08-31")) %>%
  filter(district == 2 | district == 5) %>%
  mutate(weekday = wday(dateOcc, label = TRUE)) %>%
  mutate(tod = timeOcc)

tidyMonthCrimes18$neighborhood <- as.numeric(tidyMonthCrimes18$neighborhood)

tidyMonthCrimes18$tod <- strptime(tidyMonthCrimes18$tod, tz = "America/Chicago", "%H:%M")
tidyMonthCrimes18$tod <- format(tidyMonthCrimes18$tod, format = "%H%M%S")

tidyMonthCrimes18 <- tidyMonthCrimes18 %>%
  mutate(., dayNight = ifelse(tod >= "180000" & tod < "600000", "Night", "Day")) %>% 
  dplyr::select(-dateTime, -tod, -flag_crime, -flag_administrative, -flag_unfounded, -flag_cleanup)

tidyMonthCrimes18 <- cs_missingXY(tidyMonthCrimes18, varX = x_coord, varY = y_coord, newVar = missing)
table(tidyMonthCrimes18$missing)

FALSE  TRUE 
  747     9 
tidyMonthCrimes18 <- tidyMonthCrimes18 %>% 
  cs_replace0(., var = x_coord) %>%
  cs_replace0(., var = y_coord) %>% 
  filter(., missing == FALSE)
tidyTotalCrimes18 <- totalCrimes18 %>% 
  cs_filter_count(., var = count) %>%
  cs_filter_crime(., var = crime, "part 1") %>%
  cs_crime_cat(., var = crime, crimeCatNum, "numeric") %>%
  cs_crime_cat(., var = crime, crimeCatName, "string") %>%
  cs_crime(., var = crime, violent, "violent") %>%
  cs_crime(., var = crime, property, "property") %>%
  cs_parse_month(., var = coded_month, yearVar = reportYear, month = monthVar) %>%
  cs_parse_date(., date_occur, dateVar = dateOcc, timeVar = timeOcc) %>%
  filter(district == 2 | district == 5) %>%
  mutate(weekday = wday(dateOcc, label = TRUE)) %>%
  mutate(tod = timeOcc) 

tidyTotalCrimes18$neighborhood <- as.numeric(tidyTotalCrimes18$neighborhood)

tidyTotalCrimes18$tod <- strptime(tidyTotalCrimes18$tod, tz = "America/Chicago", "%H:%M")
tidyTotalCrimes18$tod <- format(tidyTotalCrimes18$tod, format = "%H%M%S")

tidyTotalCrimes18 <- tidyTotalCrimes18 %>%
  mutate(., dayNight = ifelse(tod >= "180000" & tod < "600000", "Night", "Day")) %>% 
  dplyr::select(-dateTime, -tod, -flag_crime, -flag_administrative, -flag_unfounded, -flag_cleanup)

tidyTotalCrimes18 <- cs_missingXY(tidyTotalCrimes18, varX = x_coord, varY = y_coord, newVar = missing)
table(tidyTotalCrimes18$missing)

FALSE  TRUE 
 7729   139 
tidyTotalCrimes18 <- tidyTotalCrimes18 %>% 
  cs_replace0(., var = x_coord) %>%
  cs_replace0(., var = y_coord) %>% 
  filter(., missing == FALSE)

rm(totalCrimes18)

Combine 2018 & 2019

augustCrimes <- rbind(tidyMonthCrimes18, tidyCrimes19)

Create Spatial Objects

crimesYear18_sf <- cs_projectXY(tidyTotalCrimes18, varX = x_coord, varY = y_coord, crs = 102696)
crimes19_sf <- cs_projectXY(tidyCrimes19, varX = x_coord, varY = y_coord, crs = 102696)
augustCrimes_sf <- cs_projectXY(augustCrimes, varX = x_coord, varY = y_coord, crs = 102696)

Prep for Data by Neighborhood

sa <- c(39,28,38,51,53,54,58,46,47,48,48)
dst2 <- c(7:15,27:29, 39:45,81,82,87,88)
dst5 <- c(38,46:58,78)

Mapping

One way we work to improve the level of physical & personal security is the analysis and distribution of crime data and statistics. The original source of this crime data is http://slmpd.org/crimereports.shtml. This notebook takes the data that was previously cleaned and maps the data.

Load Spatial Data

Coordinates

xyfpse <- c(-90.2679, -90.2423, 38.6176, 38.6334)
xycwe <- c(-90.2759, -90.2368, 38.6286, 38.6552)
xybot <- c(-90.2619, -90.2409, 38.6165, 38.6296)
xydbp <- c(-90.2869, -90.2726, 38.6433, 38.6566)
xysdb <- c(-90.3026, -90.2827, 38.6456, 38.6571)
xywe <- c(-90.3020, -90.2712, 38.6517, 38.6710)
xyvp <- c(-90.2803, -90.2712, 38.6517, 38.6622)
xyac <- c(-90.2744, -90.2609, 38.6505, 38.6661)
xyfp <- c(-90.2648, -90.2543, 38.6493, 38.6655)
xylp <- c(-90.2588, -90.2437, 38.6481, 38.6624)
xyvd <- c(-90.2520, -90.2304, 38.6426, 38.6585)
xymc <- c(-90.2678, -90.2515, 38.6305, 38.6411)
xyctx <- c(-90.2581, -90.2419, 38.6299, 38.6386)
xygrv <- c(-90.2662, -90.2440, 38.6238, 38.6318)
xydst2 <- c(-90.3203, -90.2297, 38.5613, 38.6493)
xydst5 <- c(-90.3080, -90.2132, 38.6273, 38.6962)

Open Street Map from Mapbox - Basemap Tile Imagery

Load External Data

Population Data

load(here("data/nbhd_pop10.rda"))

Spatial

Combine Population & Neighborhood Spatial Data by Police District

Oganize & Filter Crime Data by Neighborhood

dst_2 <- tidyCrimes19 %>% 
  filter(., neighborhood %in% dst2) %>% 
  group_by(., neighborhood) %>%
  count() %>% 
  rename(crimeTotal = n) %>%
  left_join(nbhd_pop10, by = "neighborhood") %>% 
  mutate(., crimeRate = (crimeTotal/pop10)*1000) %>% 
  drop_na()
dst_5 <- tidyCrimes19 %>% 
  filter(., neighborhood %in% dst5) %>% 
  group_by(., neighborhood) %>%
  count() %>% 
  rename(crimeTotal = n) %>%
  left_join(nbhd_pop10, by = "neighborhood") %>% 
  mutate(., crimeRate = (crimeTotal/pop10)*1000) %>% 
  drop_na()
dst_2_pop <- left_join(nhoods_sf, dst_2, by = "neighborhood") %>% 
  st_transform(crs = 102696) %>%
  drop_na() %>% 
  subset(., neighborhood != 88)
dst_5_pop <- left_join(nhoods_sf, dst_5, by = "neighborhood") %>% 
  st_transform(crs = 102696) %>%
  drop_na()

FPSE, BOT, CWE, MC

Map Creation

FPSE
fpse_total_tm <- tm_shape(fpse_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 39) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 39) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "FPSE Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

fpse_total_tm

fpse_dn_tm <- tm_shape(fpse_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 39) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 39) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "dayNight", 
               palette = "-RdBu", 
               title.col = "Time of Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "FPSE Time of Crimes - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

fpse_dn_tm

fpse_vlnt_tm <- tm_shape(fpse_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 39) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 39) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "violent", 
               palette = "Reds", 
               title.col = "Violent") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "FPSE Violent Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

fpse_vlnt_tm

crimes19_sf %>%
  filter(neighborhood == 39) %>%
  smooth_map(., bandwidth = 0.5, style = "pretty",
  cover = fpse) -> fpse_densities

  |                                                                                                  
  |                                                                                            |   0%
  |                                                                                                  
  |=========                                                                                   |  10%
  |                                                                                                  
  |============================                                                                |  30%
  |                                                                                                  
  |==============================================                                              |  50%
  |                                                                                                  
  |================================================================                            |  70%
  |                                                                                                  
  |===================================================================================         |  90%
  |                                                                                                  
  |============================================================================================| 100%
fpse_den_tm <- tm_shape(fpse_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 39) %>% 
  tm_shape() +
    tm_fill(col = NA, 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  tm_shape(fpse_densities$polygons) +
  tm_fill(col = "level", palette = "BuPu", alpha = .60, 
    title = expression("Crimes per " * km^2)) +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "FPSE Crime Density - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

fpse_den_tm

Grove CID
grove_crimes <- st_intersection(crimes19_sf, grove_cid)
attribute variables are assumed to be spatially constant throughout all geometries
fpse_grove_tm <- tm_shape(grv_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 39) %>% 
  tm_shape() +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  tm_shape(grove_cid) +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 1, 
               lty = "solid") +
  tm_shape(grove_crimes) +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "Grove CID Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

fpse_grove_tm

CWE
cwe_total_tm <- tm_shape(cwe_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 38) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "CWE Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_total_tm

cwe_dn_tm <- tm_shape(cwe_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 38) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "dayNight", 
               palette = "-RdBu", 
               title.col = "Time of Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "CWE Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_dn_tm

cwe_vlnt_tm <- tm_shape(cwe_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 38) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "violent", 
               palette = "Reds", 
               title.col = "Violent") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "CWE Time of Crimes - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_vlnt_tm

cwe_densities <- crimes19_sf %>%
  filter(neighborhood == 38) %>%
  smooth_map(., bandwidth = 0.5, style = "pretty",
  cover = cwe)

  |                                                                                                  
  |                                                                                            |   0%
  |                                                                                                  
  |=========                                                                                   |  10%
  |                                                                                                  
  |============================                                                                |  30%
  |                                                                                                  
  |==============================================                                              |  50%
  |                                                                                                  
  |================================================================                            |  70%
  |                                                                                                  
  |===================================================================================         |  90%
  |                                                                                                  
  |============================================================================================| 100%
cwe_den_tm <- tm_shape(cwe_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_fill(col = NA, 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  tm_shape(cwe_densities$polygons) +
  tm_fill(col = "level", palette = "BuPu", alpha = .60, 
    title = expression("Crimes per " * km^2)) +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "CWE Crime Density- August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_den_tm

Medical Campus
mc_crimes <- st_intersection(crimes19_sf, med_campus)
attribute variables are assumed to be spatially constant throughout all geometries
cwe_mc_tm <- tm_shape(mc_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  tm_shape(med_campus) +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 1, 
               lty = "solid") +
  tm_shape(mc_crimes) +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "Med. Campus Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_mc_tm


mc_crimes_18 <- st_intersection(crimesYear18_sf, med_campus) %>% 
  as.data.frame()
attribute variables are assumed to be spatially constant throughout all geometries
mc_crimes <- mc_crimes %>% 
   as.data.frame()

mc_crimes_18 %>% 
  group_by(monthVar) %>% 
  count(crimeCatName) %>% 
  rename(., "Number of Crimes" = n) %>% 
  pivot_wider(names_from = monthVar, values_from = "Number of Crimes") %>% 
  replace(., is.na(.), 0) %>% 
  rename(., "Part 1 Crimes" = crimeCatName, 
         "January" = "01",
         "February" = "02",
         "March" = "03",
         "April" = "04",
         "May" = "05",
         "June" = "06",
         "July" = "07",
         "August" = "08",
         "September" = "09",
         "October" = "10",
         "November" = "11",
         "December" = "12") %>% 
  adorn_totals(., "col", name = "Total") %>% 
  adorn_totals(., "row", name = "Total") -> mc_2018

mc_crimes %>% 
  group_by(crimeCatName) %>% 
  count() %>% 
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Part 1 Crimes" = crimeCatName) -> mc_crimeCat

kable(mc_crimeCat) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("mc_crimCat.jpeg")

mc_crimes %>% 
  group_by(dayNight) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Time of Day" = dayNight) -> mc_dayNight

kable(mc_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("mc_dayNight.jpeg")

mc_larcenies <- mc_crimes %>% 
  filter(., crimeCatNum == 6)

write.csv(mc_larcenies, file = here("results/cwe/2019/august/cwe_larcenies.csv"))

write.csv(mc_crimes, file = here("results/cwe/2019/august/mc_crimes_august19.csv"))
write.csv(mc_2018, file = here("results/cwe/2019/august/mc_crimes_2018.csv"))
Cortex
ctx_crimes <- st_intersection(crimes19_sf, cortex)
attribute variables are assumed to be spatially constant throughout all geometries
cwe_ctx_tm <- tm_shape(ctx_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 38) %>% 
  tm_shape() +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  tm_shape(cortex) +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 1, 
               lty = "solid") +
  tm_shape(ctx_crimes) +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "Cortex Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

cwe_ctx_tm

Botanical Heights
bot_total_tm <- tm_shape(bot_tiles) +
  tm_rgb() +
  nhoods_sf %>%
  filter(., neighborhood == 28) %>% 
  tm_shape() +
    tm_fill(col = "#9ecae1", 
            alpha = .5) +
    tm_borders(col = "black", 
               lwd = 2, 
               lty = "dashed") +
  filter(crimes19_sf, 
         neighborhood == 28) %>%
  tm_shape() +
    tm_bubbles(size = .25, 
               col = "crimeCatName", 
               palette = "Set1", 
               title.col = "Part 1 Crimes") +
  tm_credits("© Mapbox, © OpenStreetMap", position = c("left", "BOTTOM")) +
  tm_layout(
    main.title = "Botanical Heights Total Crime - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

bot_total_tm

District 2 Density Maps
dst2_rateMap <- tm_shape(dst2_tiles) +
  tm_rgb() +
  tm_shape(dst_2_pop) +
  tm_polygons(col = "crimeRate",
              palette = "BuPu",
              style = "jenks",
              title = "Crimes per 1,000 Residents") +
  tm_text("neighborhood", shadow=TRUE) +
  tm_layout(
    main.title = "District 2 Crime Rates - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

dst2_rateMap

dst_2_statsTotal <- describe(dst_2_pop$crimeTotal)
dst_2_statsRate <- describe(dst_2_pop$crimeRate)

dst_2_statsTotal
dst_2_statsRate
dst5_rateMap <- tm_shape(dst5_tiles) +
  tm_rgb() +
  tm_shape(dst_5_pop) +
  tm_polygons(col = "crimeRate",
              palette = "BuPu",
              style = "jenks",
              title = "Crimes per 1,000 Residents") +
  tm_text("neighborhood", shadow=TRUE) +
  tm_layout(
    main.title = "District 5 Crime Rates - August 2019",
    frame = FALSE,
    legend.bg.color = "white", 
    legend.frame=TRUE,
    legend.outside = TRUE,
    legend.position = c("right", "bottom")) 

dst5_rateMap

dst_5_statsTotal <- describe(dst_5_pop$crimeTotal)
dst_5_statsRate <- describe(dst_5_pop$crimeRate)

dst_5_statsTotal
dst_5_statsRate

Save Maps

Clean Workspace

rm(fpse_total_tm, fpse_dn_tm, fpse_vlnt_tm, fpse_den_tm, fpse_grove_tm, cwe_total_tm, cwe_dn_tm, cwe_vlnt_tm, cwe_den_tm, cwe_mc_tm, cwe_ctx_tm, bot_total_tm, fpse_tiles, cwe_tiles, bot_tiles, mc_tiles, ctx_tiles, grv_tiles, dst_2, dst_5, dst2_tiles, dst5_tiles)

Tables

FPSE Tables

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(crimeCatName) %>% 
  count() %>% 
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Part 1 Crimes" = crimeCatName) -> fpse_crimeCat

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(weekday) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Day of the Week" = weekday) -> fpse_weekDay

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(violent) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Crimes Against Persons" = violent) -> fpse_violent


tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(dayNight) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Time of Day" = dayNight) -> fpse_dayNight

tidyTotalCrimes18 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(monthVar) %>% 
  count(crimeCatName) %>% 
  rename(., "Number of Crimes" = n) %>% 
  pivot_wider(names_from = monthVar, values_from = "Number of Crimes") %>% 
  replace(., is.na(.), 0) %>% 
  rename(., "Part 1 Crimes" = crimeCatName, 
         "January" = "01",
         "February" = "02",
         "March" = "03",
         "April" = "04",
         "May" = "05",
         "June" = "06",
         "July" = "07",
         "August" = "08",
         "September" = "09",
         "October" = "10",
         "November" = "11",
         "December" = "12") %>% 
  adorn_totals(., "col", name = "Total") %>% 
  adorn_totals(., "row", name = "Total") -> fpse_2018

tidyTotalCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(monthVar) %>% 
  count(crimeCatName) %>% 
  rename(., "Number of Crimes" = n) %>% 
  pivot_wider(names_from = monthVar, values_from = "Number of Crimes") %>% 
  replace(., is.na(.), 0) %>% 
  rename(., "Part 1 Crimes" = crimeCatName, 
         "January" = "01",
         "February" = "02",
         "March" = "03",
         "April" = "04",
         "May" = "05",
         "June" = "06",
         "July" = "07",
         "August" = "08") %>% 
  adorn_totals(., "col", name = "Total") %>% 
  adorn_totals(., "row", name = "Total") -> fpse_2019

fpse_larcenies <- tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  filter(., crimeCatNum == 6)

write.csv(fpse_larcenies, file = here("results/fpse/2019/august/larcenies.csv"))

fpse_larcenies %>% 
  group_by(weekday) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Day of the Week" = weekday) -> fpse_larcenies_weekDay

fpse_larcenies %>% 
  group_by(dayNight) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Time of Day" = dayNight) -> fpse_larcenies_dayNight
kable(fpse_crimeCat) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_crimCat.jpeg")

kable(fpse_weekDay) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_weekDay.jpeg")

kable(fpse_violent) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_violent.jpeg")

kable(fpse_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_dayNight.jpeg")

kable(fpse_2018) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_2018.jpeg")

kable(fpse_2019) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_2019.jpeg")

kable(fpse_larcenies_weekDay) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_larcenies_weekDay.jpeg")

kable(fpse_larcenies_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("fpse_larcenies_dayNight.jpeg")

CWE Tables

kable(cwe_crimeCat) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_crimCat.jpeg")

kable(cwe_weekDay) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_weekDay.jpeg")

kable(cwe_violent) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_violent.jpeg")

kable(cwe_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_dayNight.jpeg")

kable(cwe_2018) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_2018.jpeg")

kable(cwe_2019) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_2019.jpeg")

kable(cwe_larcenies_weekDay) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_larcenies_weekDay.jpeg")

kable(cwe_larcenies_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("cwe_larcenies_dayNight.jpeg")
head(fpse_2018) 
       Part 1 Crimes January February March April May June July August September October November
  Aggravated Assault       2        2     0     3   7    5    4      3         1       7        0
            Homicide       1        0     0     0   0    0    0      0         0       0        0
             Larceny       5        3     6     7  20    5   13     12        14       9       10
 Motor Vehicle Theft       2        1     2     0   3    3    3      2         2       2        2
            Burgalry       0        1     1     3   0    1    1      1         0       1        0
               Arson       0        0     1     0   0    0    0      0         0       0        0
 December Total
        3    37
        0     1
        3   107
        2    24
        0     9
        0     1
write.csv(fpse_2018, file = here("results/fpse/2019/august/fpse_2018.csv"))
head(fpse_2019)
       Part 1 Crimes January February March April May June July August Total
             Larceny       8       10    14    12   8   20   17     19   108
 Motor Vehicle Theft       3        6     1     2   0    2    7      2    23
             Robbery       1        0     1     1   2    5    2      1    13
  Aggravated Assault       0        3     1     2   2    4    2      0    14
               Arson       0        0     1     0   0    0    1      0     2
            Burgalry       0        0     1     1   0    0    3      1     6
write.csv(fpse_2019, file = here("results/fpse/2019/august/fpse_2019.csv"))
head(cwe_2018)
       Part 1 Crimes January February March April May June July August September October November
  Aggravated Assault       7        0     1     7   6   11    6      4         7       4        4
            Burgalry       4        5     6     7   6   13   10     15         7       9       11
            Homicide       1        0     0     0   0    0    0      0         0       0        0
             Larceny      95       61    52    53  65   90  131     89        75      82       60
 Motor Vehicle Theft       9        6     7     9  12    6    6      5        10      12        6
             Robbery       2        2     8    10   1    8    3      9         6       8        5
 December Total
       10    67
        2    95
        0     1
       53   906
        9    97
        6    68
write.csv(cwe_2018, file = here("results/cwe/2019/august/cwe_2018.csv"))
head(cwe_2019)
       Part 1 Crimes January February March April May June July August Total
  Aggravated Assault       8        4    10     3   8   14    4     10    61
            Burgalry       3        5     5     9  13    7   12     18    72
             Larceny      49       63    65    66  68   60   76     78   525
 Motor Vehicle Theft      12        8     3    10  12   10    5     11    71
             Robbery       5        5     2     6   7    3    4      8    40
               Arson       0        0     1     0   0    0    0      0     1
write.csv(cwe_2019, file = here("results/cwe/2019/august/cwe_2019.csv"))

Botanical Heights

tidyCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(crimeCatName) %>% 
  count() %>% 
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Part 1 Crimes" = crimeCatName) -> bot_crimeCat

tidyCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(weekday) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Day of the Week" = weekday) -> bot_weekDay

tidyCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(violent) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Crimes Against Persons" = violent) -> bot_violent


tidyCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(dayNight) %>% 
  count() %>%
  adorn_totals(., "row", name = "Total") %>%
  rename(., "Number of Crimes" = n, "Time of Day" = dayNight) -> bot_dayNight

tidyTotalCrimes18 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(monthVar) %>% 
  count(crimeCatName) %>% 
  rename(., "Number of Crimes" = n) %>% 
  pivot_wider(names_from = monthVar, values_from = "Number of Crimes") %>% 
  replace(., is.na(.), 0) %>% 
  rename(., "Part 1 Crimes" = crimeCatName, 
         "January" = "01",
         "February" = "02",
         "March" = "03",
         "April" = "04",
         "May" = "05",
         "June" = "06",
         "July" = "07",
         "August" = "08",
         "September" = "09",
         "October" = "10",
         "November" = "11",
         "December" = "12") %>% 
  adorn_totals(., "col", name = "Total") %>% 
  adorn_totals(., "row", name = "Total") -> bot_2018
write.csv(bot_2018, file = here("results/bot/2019/bot_2018.csv"))

tidyTotalCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(monthVar) %>% 
  count(crimeCatName) %>% 
  rename(., "Number of Crimes" = n) %>% 
  pivot_wider(names_from = monthVar, values_from = "Number of Crimes") %>% 
  replace(., is.na(.), 0) %>% 
  rename(., "Part 1 Crimes" = crimeCatName, 
         "January" = "01",
         "February" = "02",
         "March" = "03",
         "April" = "04",
         "May" = "05",
         "June" = "06",
         "July" = "07",
         "August" = "08") %>% 
  adorn_totals(., "col", name = "Total") %>% 
  adorn_totals(., "row", name = "Total") -> bot_2019
write.csv(bot_2019, file = here("results/bot/2019/bot_2019.csv"))
kable(bot_crimeCat) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("bot_crimCat.jpeg")

kable(bot_weekDay) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("bot_weekDay.jpeg")

kable(bot_violent) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("bot_violent.jpeg")

kable(bot_dayNight) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F, position = "center") %>% 
  save_kable("bot_dayNight.jpeg")

Graphs/Charts

need to change file save locations

FPSE Graphs

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(weekday) %>% 
  count() %>%
  ggplot(., aes(x=weekday, y=n, group=1)) +
    geom_line(color="blue") +
    geom_point() + 
    xlab("Day of Week") + ylab("Total Crimes") +
    ggtitle("FPSE Total Crimes by Days of the Week")

ggsave(here("results/graphs/fpse_crime_weekday.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(crimeCatName) %>%
  ggplot(., aes(weekday)) +
    geom_bar(aes(fill = crimeCatName), position=position_dodge()) +
    xlab("Day of Week") + ylab("Total Crimes") +
    ggtitle("FPSE Crimes by Day & Category") + 
    labs(fill = "Part 1 Crimes") +
    scale_fill_brewer(palette = "Spectral")

ggsave(here("results/graphs/fpse_crimeCat_weekday.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

tidyCrimes19 %>% 
  filter(., neighborhood == 39) %>% 
  group_by(dayNight) %>%
  count() %>% 
  ggplot(., aes(x=dayNight, y=n, fill = dayNight)) +
    geom_bar(stat="identity", position=position_dodge(), colour="black") +
    xlab("Time of Day") + ylab("Total Crimes") +
    ggtitle("FPSE Crimes by Time of Day") + 
    labs(fill = "Time")

ggsave(here("results/graphs/fpse_crime_timeDay.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

CWE Graphs

tidyCrimes19 %>% 
  filter(., neighborhood == 38) %>% 
  group_by(weekday) %>% 
  count() %>%
  ggplot(., aes(x=weekday, y=n, group=1)) +
    geom_line(color="blue") +
    geom_point() + 
    xlab("Day of Week") + ylab("Total Crimes") +
    ggtitle("CWE Total Crimes by Days of the Week")

ggsave(here("results/graphs/cwe_crime_weekday.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

tidyCrimes19 %>% 
  filter(., neighborhood == 38) %>% 
  group_by(crimeCatName) %>%
  ggplot(., aes(weekday)) +
    geom_bar(aes(fill = crimeCatName), position=position_dodge()) +
    xlab("Day of Week") + ylab("Total Crimes") +
    ggtitle("CWE Crimes by Day & Category") + 
    labs(fill = "Part 1 Crimes") +
    scale_fill_brewer(palette = "Spectral")

ggsave(here("results/graphs/cwe_crimeCat_weekday.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

tidyCrimes19 %>% 
  filter(., neighborhood == 38) %>% 
  group_by(dayNight) %>%
  count() %>% 
  ggplot(., aes(x=dayNight, y=n, fill = dayNight)) +
    geom_bar(stat="identity", position=position_dodge(), colour="black") +
    xlab("Time of Day") + ylab("Total Crimes") +
    ggtitle("CWE Crimes by Time of Day") + 
    labs(fill = "Time") 

ggsave(here("results/graphs/cwe_crime_timeDay.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

BOT

tidyCrimes19 %>% 
  filter(., neighborhood == 28) %>% 
  group_by(weekday) %>% 
  count() %>%
  ggplot(., aes(x=weekday, y=n, group=1)) +
    geom_line(color="blue") +
    geom_point() + 
    expand_limits(y=0) +
    xlab("Day of Week") + ylab("Total Crimes") +
    ggtitle("BOT Total Crimes by Days of the Week")

ggsave(here("results/graphs/bot_crime_weekday.jpeg"), dpi = 300)
Saving 7.29 x 4.51 in image

LS0tCnRpdGxlOiAiU2FpbnQgTG91aXMgQ2l0eSBDcmltZSBEYXRhIC0gTW9udGhseSBSZXBvcnRzIgphdXRob3I6ICJKZXMgU3RldmVucywgTS5BLiIKZGF0ZTogJyhgciBmb3JtYXQoU3lzLnRpbWUoKSwgIiVCICVkLCAlWSIpYCknCm91dHB1dDoKICBnaXRodWJfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0CmFsd2F5c19hbGxvd19odG1sOiB5ZXMKLS0tCgpgYGB7ciBTZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMjIEludHJvZHVjdGlvbiAKCltXYXNoaW5ndG9uIFVuaXZlcnNpdHkgTWVkaWNhbCBDZW50ZXIgUmVkZXZlbG9wbWVudCBDb3Jwb3JhdGlvbl0oaHR0cDovL3d1bWNyYy5jb20pIGlzIGEgcGFydG5lcnNoaXAgYmV0d2VlbiBCSkMgSGVhbHRoIENhcmUgYW5kIFdhc2hpbmd0b24gVW5pdmVyc2l0eSBTY2hvb2wgb2YgTWVkaWNpbmUgYW5kIHdvcmtzIHRvIGltcHJvdmUgdGhlIHF1YWxpdHkgb2YgbGlmZSBmb3IgdGhlIG5laWdoYm9yaG9vZHMgc3Vycm91bmRpbmcgdGhlIG1lZGljYWwgY2FtcHVzLiBJbiBvcmRlciB0byBhY2hpZXZlIHRoaXMgZ29hbCBpbiBGb3Jlc3QgUGFyayBTb3V0aGVhc3QgYW5kIHRoZSBDZW50cmFsIFdlc3QgRW5kICwgV1VNQ1JDIGhhcyBpbnZlc3RlZCBtaWxsaW9ucyBvZiBkb2xsYXJzIHRvd2FyZCByZWdlbmVyYXRpbmcgdGhlIG1hcmtldCBmb3IgcHJpdmF0ZSBpbnZlc3RtZW50IGluIGJ1c2luZXNzZXMgYW5kIHJlYWwgZXN0YXRlLCBlbmhhbmNpbmcgaHVtYW4gYW5kIHNvY2lhbCBzZXJ2aWNlIG9wcG9ydHVuaXRpZXMsIGFuZCBpbXByb3ZpbmcgdGhlIGxldmVsIG9mIHBoeXNpY2FsIGFuZCBwZXJzb25hbCBzZWN1cml0eS4KCk9uZSB3YXkgd2Ugd29yayB0byBpbXByb3ZlIHRoZSBsZXZlbCBvZiBwaHlzaWNhbCAmIHBlcnNvbmFsIHNlY3VyaXR5IGlzIHRoZSBhbmFseXNpcyBhbmQgZGlzdHJpYnV0aW9uIG9mIGRhdGEuIFRoZSBvcmlnaW5hbCBzb3VyY2Ugb2YgdGhpcyBjcmltZSBkYXRhIGlzIDxodHRwOi8vc2xtcGQub3JnL2NyaW1lcmVwb3J0cy5zaHRtbD4uIFRoaXMgbm90ZWJvb2sgdXNlcyBwcmltYXJpbHkgYGNvbXBzdGF0cmAgdG8gYWNjZXNzIGFuZCBjbGVhbiB0aGUgY3JpbWUgZGF0YS4gCgojIyBSIE1hcmtkb3duCgpgYGB7ciBMb2FkIERlcGVuZGVuY2llcywgaW5jbHVkZSA9IEZBTFNFfQojIHRpZHl2ZXJzZSBwYWNrYWdlcwpsaWJyYXJ5KGdncGxvdDIpICAgICAgICMgcGxvdHRpbmcgZGF0YQpsaWJyYXJ5KHN0cmluZ3IpICAgICAgICMgd3JhcHBlcnMgZm9yIGNvbW1vbiBzdHJpbmcgb3BlcmF0aW9ucwpsaWJyYXJ5KHRpZHlyKSAgICAgICAgICMgdGlkeSBkYXRhCmxpYnJhcnkoZHBseXIpICAgICAgICAgIyBkYXRhIG1hbmlwdWxhdGlvbgpsaWJyYXJ5KG1hZ3JpdHRyKSAgICAgICMgcGlwZSBvcGVyYXRvcgpsaWJyYXJ5KHJlYWR4bCkgICAgICAgICMgcmVhZCAmIHdyaXRlIGV4Y2VsIGZpbGVzCmxpYnJhcnkobHVicmlkYXRlKQoKIyBzcGF0aWFsIHBhY2thZ2VzCmxpYnJhcnkodG1hcCkgICAgICAgICAjIG1hcCBsYXlvdXRzCmxpYnJhcnkodG1hcHRvb2xzKSAgICAjIHRvb2xzIGZvciBoYW5kZWxpbmcgc3BhdGlhbCAKbGlicmFyeShvbGR0bWFwdG9vbHMpCmxpYnJhcnkoc2YpICAgICAgICAgICAjIHNwYXRpYWwgZGF0YSB0b29scwpsaWJyYXJ5KGNlcmFtaWMpICAgICAgIyBkb3dubG9hZCBvbmxpbmUgaW1hZ2VyeSB0aWxlcwpsaWJyYXJ5KGNvbXBzdGF0cikgICAgIyB0b29scyBmb3IgU1RMIGNyaW1lIGRhdGEKbGlicmFyeShyYXN0ZXIpICAgICAgICMgZ2VvZ3JhcGljIGRhdGEgYW5hbHlzaXMgJiBtb2RlbGluZwoKIyBvdGhlciBwYWNrYWdlcwpsaWJyYXJ5KGhlcmUpICAgICAgICAgIyBmaWxlIHBhdGggbWFuYWdlbWVudApsaWJyYXJ5KFJDb2xvckJyZXdlcikgIyBjeW50aGlhIGJyZXdlciBjb2xvciBwYWxldHRlcwpsaWJyYXJ5KHZpcmlkaXMpICAgICAgIyBjb2xvciBwYWxldHRlcwpsaWJyYXJ5KGthYmxlRXh0cmEpICAgIyBleHBvcnRpbmcgcHJldHR5IHRhYmxlcwpsaWJyYXJ5KGphbml0b3IpICAgICAgIyB0b29scyBmb3IgZXhhbWluaW5nIGRhdGEKYGBgCgojIyBUaWR5IGRhdGEKCiMjIyBDcmVhdGUgYW4gSW5kZXgKCmBgYHtyIENyZWF0ZSBDcmltZSBJbmRleH0KaSA8LSBjc19jcmVhdGVfaW5kZXgoKQpgYGAKCiMjIyBHZXQgRGF0YSAtIDIwMTkKCmBgYHtyIFB1bGwgMjAxOSBEYXRhfQp1cGRhdGUgPC0gY3NfbGFzdF91cGRhdGUoKQp1cGRhdGUgPC0gc3Ryc3BsaXQodXBkYXRlLCAiICIpW1sxXV0KY19tb250aCA8LSB1cGRhdGVbWzFdXQpjX3llYXIgPC0gYXMubnVtZXJpYyh1cGRhdGVbWzJdXSkKeWVhckxpc3QxOSA8LSBjc19nZXRfZGF0YSh5ZWFyID0gY195ZWFyLCBpbmRleCA9IGkpCmBgYAoKIyMjIERvd25sb2FkIEN1cnJlbnQgTW9udGgKCmBgYHtyIFZhbGlkYXRlIDIwMTkgRGF0YX0KY3NfdmFsaWRhdGUoeWVhckxpc3QxOSwgeWVhciA9IDIwMTkpCmBgYAoKYGBge3IgU3RhbmRhcmRpemUgMjAxOSBEYXRhfQp0b3RhbENyaW1lczE5IDwtIGNzX2NvbGxhcHNlKHllYXJMaXN0MTkpCmBgYAoKCmBgYHtyIFByaW50IEN1cnJlbnQgTW9udGh9CnByaW50KGNfbW9udGgpCmBgYAoKCmBgYHtyIEV4dHJhY3QgQXVndXN0IDIwMTkgRGF0YX0KY3JpbWVzMTkgPC0gY3NfZXh0cmFjdF9tb250aCh5ZWFyTGlzdDE5LCBtb250aCA9ICJBdWd1c3QiKSAKYGBgCgojIyMgQ2xlYW4gJiBDYXRlZ29yaXplIERhdGEgLSAyMDE5CgpgY3NfZmlsdGVyX2NvdW50YCByZW1vdmVzIG5lZ2F0aXZlIGNvdW50cy4gTmVnYXRpdmUgY291bnRzLCAtMSwgaW4gdGhlIGNvdW50IGNvbHVtbiBtZWFucyB0aGF0IHRoZSBjcmltZSwgb3IgY2hhcmdlIGluIHRoaXMgc3BlY2lmaWMgb2JzZXJ2YXRpb24gaGFzIGVpdGhlciBiZWVuIGRlZW1lZCB1bmZvdW5kZWQsIG9yIHRoZSBjcmltZSBoYXMgYmVlbiB1cCBjb2RlZC4gV2UgZG8gbm90IHdhbnQgdG8gbWFwIHRoaXMgZGF0YS4gCgpNYW55IG9mIHRoZSBhbmFseXNlcyB3ZSBjb25kdWN0IGluY2x1ZGUgY29tcGFyaXNvbnMgYmV0d2VlbiB2aW9sZW50ICYgbm9uLXZpb2xlbnQgY3JpbWUsIGNvbXBhcmlzb25zIG9uIHRoZSBhbW91bnQgb2YgY3JpbWVzIGhhcHBlbmluZyBpbiBlYWNoIGNyaW1lIGNhdGVvZ3kgb3ZlciB0aW1lLCBhbmQgaWYgY3JpbWVzIG9jY3VyIGR1cmluZyB0aGUgZGF5IG9yIGF0IG5pZ2h0LiBUaGUgZm9sbG93aW5nIGNvZGUgY2VhdGVzIHZhcmlhYmxlcyB0byBjb25kdWN0IHRoZXNlIGFuYWx5c2VzLiAKCmBjc19jcmltZV9jYXRgIGNyZWF0ZXMgYSB2YXJpYWJsZSB3aXRoIHRoZSBuYW1lcyBvZiB0aGUgY3JpbWUuIAoKYGNzX2NyaW1lYCBjcmVhdGVzIGEgbG9naWMgdmFyaWFibGUgYW5kIGNvZGVzIHZpb2xlbnQgY3JpbWVzIGFzIGBUUlVFYCBhbmQgbm9uLXZpb2xlbnQgY3JpbWVzIGFzIGBGQUxTRWAKCmBjc19wYXJzZV9kYXRlYCBjcmVhdGVzIHR3byBjb2x1bW5zIHNlcGFyYXRpbmcgdGhlIGBEYXRlIE9jY3VyYCB2YXJpYWJsZS4gVGhlIHR3byBjb2x1bXMgYXJlIGFzIGZvbGxvd3M6IG9uZSBjb250YWlucyB0aGUgZGF0ZSAtIG1vbnRoLCBkYXRlLCBhbmQgeWVhciwgYW5kIHRoZSBvdGhlciBjb250YWlucyB0aGUgaG91ciBhbmQgbWludXRlLiBUaGlzIGlzIHVzZWQgYmVjYXVzZSBjcmltZXMgY29kZWQgaW4gdGhlIG1vc3QgcmVjZW50IG1vbnRoLCBjYW4gY29udGFpbiBkYXRlcyB0aGF0IG9jY3VyZWQsIGluIHByZXZpb3VzIG1vbnRocyBvciB5ZWFycyAmIGluIHRoaXMgcmVwb3J0IHdlIG9ubHkgd2FudCB0byBtYXAgdGhlIGNyaW1lcyB0aGF0IG9jY3VyZWQgaW4gdGhlIHBhc3QgbW9udGguIAoKYGZpbHRlcmAgaXMgYSBgZHBseXJgIGZ1bmN0aW9uIHRoYXQgZmlsdGVycyBvdXQgYW55IGRhdGVzIHRoYXQgb2NjdXIgYmVmb3JlIHRoZSBvdXIgc2VsZWN0ZWQgZGF0ZSwgYW5kIGFsc28gZmlsdGVycyBvdXQgY3JpbWVzIHRoYXQgZGlkIG5vdCBoYXBwZW4gaW4gZWl0aGVyIERpc3RyaWN0IDIgb3IgZGlzdHJpY3QgNS4gCgpgbXV0YXRlYCBhZGRzIGEgdmFyaWFibGUgdGhhdCBjb2RlcyBhbmQgbGFiZWxzIHRoZSBkYXlzIG9mIHRoZSB3ZWVrIGZvciBlYWNoIGNyaW1lIHRoYXQgb2NjdXJyZWQsIGFuZCBjcmVhdGVzIGFub3RoZXIgdGltZSBvZiBkYXkgdmFyaWFibGUgCgpgYGB7ciBDcmVhdGVzIDIwMTkgQ2F0ZWdvcml6ZWQgVGlkeSBDcmltZSBGaWxlfQp0aWR5Q3JpbWVzMTkgPC0gY3JpbWVzMTkgJT4lIAogIGNzX2ZpbHRlcl9jb3VudCguLCB2YXIgPSBjb3VudCkgJT4lCiAgY3NfZmlsdGVyX2NyaW1lKC4sIHZhciA9IGNyaW1lLCAicGFydCAxIikgJT4lCiAgY3NfY3JpbWVfY2F0KC4sIHZhciA9IGNyaW1lLCBjcmltZUNhdE51bSwgIm51bWVyaWMiKSAlPiUKICBjc19jcmltZV9jYXQoLiwgdmFyID0gY3JpbWUsIGNyaW1lQ2F0TmFtZSwgInN0cmluZyIpICU+JQogIGNzX2NyaW1lKC4sIHZhciA9IGNyaW1lLCB2aW9sZW50LCAidmlvbGVudCIpICU+JQogIGNzX2NyaW1lKC4sIHZhciA9IGNyaW1lLCBwcm9wZXJ0eSwgInByb3BlcnR5IikgJT4lCiAgY3NfcGFyc2VfZGF0ZSguLCBkYXRlX29jY3VyLCBkYXRlVmFyID0gZGF0ZU9jYywgdGltZVZhciA9IHRpbWVPY2MpICU+JQogIGZpbHRlcihkYXRlT2NjID49IGFzLkRhdGUoIjIwMTktMDgtMDEiKSkgJT4lCiAgZmlsdGVyKGRpc3RyaWN0ID09IDIgfCBkaXN0cmljdCA9PSA1KSAlPiUKICBtdXRhdGUod2Vla2RheSA9IHdkYXkoZGF0ZU9jYywgbGFiZWwgPSBUUlVFKSkgJT4lCiAgbXV0YXRlKHRvZCA9IHRpbWVPY2MpCgp0aWR5Q3JpbWVzMTkkbmVpZ2hib3Job29kIDwtIGFzLm51bWVyaWModGlkeUNyaW1lczE5JG5laWdoYm9yaG9vZCkKYGBgCgpgc3RycHRpbWVgIGFuZCBgZm9ybWF0YCB0YWtlcyB0aGUgbmV3IHRpbWUgdmFyaWFibGUgYW5kIGZvcm1hdHMgaXQgdG8gYSBjaGFyYWN0ZXIgc28gdGhhdCB3ZSBjYW4gZGV0ZXJtaW5lIGlmIHRoZSBjcmltZSBvY2N1cmVkIGF0IGRheSBvciBhdCBuaWdodCwgYW5kIGNyZWF0ZXMgYSBzZWNvbmQgY29kZWQgdmFyaWFibGUgdGhhdCBsYWJlbHMgZWFjaCBvYnNlcnZhdGlvbnMgYXMgZGF5IG9yIG5pZ2h0IGJhc2VkIG9uIHRoZSBuZXdseSBmb3JtYXRlZCB0aW1lIHZhcmlhYmxlLiAKCmBzZWxlY3RgIGRyb3BzIHRoZSB1bm5lZWRlZCB2YXJpYWJsZXMuIAoKYGNzX21pc3NpbmdfWFlgIGRldGVybWluZXMgd2hhdCBkYXRhIGRvZXMgbm90IGhhdmUgeCAmIHkgY29vcmRpbmF0ZXMsIGFuZCB0aGVyZWZvcmUgY2Fubm90IGJlIGFjY3VyYXRlbHkgbWFwcGVkLiAKCmBjc19yZXBsYWNlMGAgcmVwbGFjZXMgbWlzc2luZyB4ICYgeSBjb29yZGluYXRlcyB3aXRoIGBOQWAsIGFuZCBkcm9wcyB0aGUgbWlzc2luZyBkYXRhLiAKCmBgYHtyIENsZWFucyAyMDE5IFRpbWUgRGF0YSAmIE1pc3NpbmcgU3BhdGlhbCBEYXRhfQp0aWR5Q3JpbWVzMTkkdG9kIDwtIHN0cnB0aW1lKHRpZHlDcmltZXMxOSR0b2QsIHR6ID0gIkFtZXJpY2EvQ2hpY2FnbyIsICIlSDolTSIpCnRpZHlDcmltZXMxOSR0b2QgPC0gZm9ybWF0KHRpZHlDcmltZXMxOSR0b2QsIGZvcm1hdCA9ICIlSCVNJVMiKQoKdGlkeUNyaW1lczE5IDwtIHRpZHlDcmltZXMxOSAlPiUKICBtdXRhdGUoLiwgZGF5TmlnaHQgPSBpZmVsc2UodG9kID49ICIxODAwMDAiICYgdG9kIDwgIjYwMDAwMCIsICJOaWdodCIsICJEYXkiKSkgJT4lIAogIGRwbHlyOjpzZWxlY3QoLWRhdGVUaW1lLCAtdG9kLCAtZmxhZ19jcmltZSwgLWZsYWdfYWRtaW5pc3RyYXRpdmUsIC1mbGFnX3VuZm91bmRlZCwgLWZsYWdfY2xlYW51cCkKCnRpZHlDcmltZXMxOSA8LSBjc19taXNzaW5nWFkodGlkeUNyaW1lczE5LCB2YXJYID0geF9jb29yZCwgdmFyWSA9IHlfY29vcmQsIG5ld1ZhciA9IG1pc3NpbmcpCnRhYmxlKHRpZHlDcmltZXMxOSRtaXNzaW5nKQoKdGlkeUNyaW1lczE5IDwtIHRpZHlDcmltZXMxOSAlPiUgCiAgY3NfcmVwbGFjZTAoLiwgdmFyID0geF9jb29yZCkgJT4lCiAgY3NfcmVwbGFjZTAoLiwgdmFyID0geV9jb29yZCkgJT4lIAogIGZpbHRlciguLCBtaXNzaW5nID09IEZBTFNFKSAKYGBgCgojIyBUb3RhbCBDcmltZXMgMjAxOSAtIENsZWFuCgpgYGB7cn0KdG90YWxZZWFybHlDcmltZXMxOSA8LSBjc19jb2xsYXBzZSh5ZWFyTGlzdDE5KQoKdGlkeVRvdGFsQ3JpbWVzMTkgPC0gdG90YWxZZWFybHlDcmltZXMxOSAlPiUgCiAgY3NfZmlsdGVyX2NvdW50KC4sIHZhciA9IGNvdW50KSAlPiUKICBjc19maWx0ZXJfY3JpbWUoLiwgdmFyID0gY3JpbWUsICJwYXJ0IDEiKSAlPiUKICBjc19jcmltZV9jYXQoLiwgdmFyID0gY3JpbWUsIGNyaW1lQ2F0TnVtLCAibnVtZXJpYyIpICU+JQogIGNzX2NyaW1lX2NhdCguLCB2YXIgPSBjcmltZSwgY3JpbWVDYXROYW1lLCAic3RyaW5nIikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHZpb2xlbnQsICJ2aW9sZW50IikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHByb3BlcnR5LCAicHJvcGVydHkiKSAlPiUKICBjc19wYXJzZV9tb250aCguLCB2YXIgPSBjb2RlZF9tb250aCwgeWVhclZhciA9IHJlcG9ydFllYXIsIG1vbnRoID0gbW9udGhWYXIpICU+JQogIGNzX3BhcnNlX2RhdGUoLiwgZGF0ZV9vY2N1ciwgZGF0ZVZhciA9IGRhdGVPY2MsIHRpbWVWYXIgPSB0aW1lT2NjKSAlPiUKICBmaWx0ZXIoZGlzdHJpY3QgPT0gMiB8IGRpc3RyaWN0ID09IDUpICU+JQogIG11dGF0ZSh3ZWVrZGF5ID0gd2RheShkYXRlT2NjLCBsYWJlbCA9IFRSVUUpKSAlPiUKICBtdXRhdGUodG9kID0gdGltZU9jYykgCgp0aWR5VG90YWxDcmltZXMxOSRuZWlnaGJvcmhvb2QgPC0gYXMubnVtZXJpYyh0aWR5VG90YWxDcmltZXMxOSRuZWlnaGJvcmhvb2QpCgp0aWR5VG90YWxDcmltZXMxOSR0b2QgPC0gc3RycHRpbWUodGlkeVRvdGFsQ3JpbWVzMTkkdG9kLCB0eiA9ICJBbWVyaWNhL0NoaWNhZ28iLCAiJUg6JU0iKQp0aWR5VG90YWxDcmltZXMxOSR0b2QgPC0gZm9ybWF0KHRpZHlUb3RhbENyaW1lczE5JHRvZCwgZm9ybWF0ID0gIiVIJU0lUyIpCgp0aWR5VG90YWxDcmltZXMxOSA8LSB0aWR5VG90YWxDcmltZXMxOSAlPiUKICBtdXRhdGUoLiwgZGF5TmlnaHQgPSBpZmVsc2UodG9kID49ICIxODAwMDAiICYgdG9kIDwgIjYwMDAwMCIsICJOaWdodCIsICJEYXkiKSkgJT4lIAogIGRwbHlyOjpzZWxlY3QoLWRhdGVUaW1lLCAtdG9kLCAtZmxhZ19jcmltZSwgLWZsYWdfYWRtaW5pc3RyYXRpdmUsIC1mbGFnX3VuZm91bmRlZCwgLWZsYWdfY2xlYW51cCkKCnRpZHlUb3RhbENyaW1lczE5IDwtIGNzX21pc3NpbmdYWSh0aWR5VG90YWxDcmltZXMxOSwgdmFyWCA9IHhfY29vcmQsIHZhclkgPSB5X2Nvb3JkLCBuZXdWYXIgPSBtaXNzaW5nKQp0YWJsZSh0aWR5VG90YWxDcmltZXMxOSRtaXNzaW5nKQoKdGlkeVRvdGFsQ3JpbWVzMTkgPC0gdGlkeVRvdGFsQ3JpbWVzMTkgJT4lIAogIGNzX3JlcGxhY2UwKC4sIHZhciA9IHhfY29vcmQpICU+JQogIGNzX3JlcGxhY2UwKC4sIHZhciA9IHlfY29vcmQpICU+JSAKICBmaWx0ZXIoLiwgbWlzc2luZyA9PSBGQUxTRSkKCnJtKHRvdGFsQ3JpbWVzMTgpCmBgYAoKCiMjIyBHZXQgRGF0YSAtIDIwMTgKCmBgYHtyIERvd25sb2FkIDIwMTggRGF0YX0KeWVhckxpc3QxOCA8LSBjc19nZXRfZGF0YSh5ZWFyID0gMjAxOCwgaW5kZXggPSBpKQpgYGAKCiMjIyBEYXRhIFByZXBlcmF0aW9uCgpgYGB7ciBWYWxpZGF0ZSAyMDE4IERhdGF9CmNzX3ZhbGlkYXRlKHllYXJMaXN0MTgsIHllYXIgPSAyMDE4KQpgYGAKCiMjIyBEb3dubG9hZCBMYXN0IFllYXIncyBNb250aApgYGB7ciBFeHRyYWN0IExhc3QgWWVhcnMgQ3JpbWUgRGF0YSBGb3IgQ3VycmVudCBNb250aH0KdG90YWxDcmltZXMxOCA8LSBjc19jb2xsYXBzZSh5ZWFyTGlzdDE4KQptb250aENyaW1lczE4IDwtIGNzX2V4dHJhY3RfbW9udGgoeWVhckxpc3QxOCwgbW9udGggPSAiQXVndXN0IikKcm0oeWVhckxpc3QxOCkKYGBgCgojIyMgQ2xlYW4gJiBDYXRlZ29yaXplIERhdGEgLSAyMDE4CgpgYGB7ciBGaWx0ZXIgJiBDYXRlZ29yaXplIDIwMTggRGF0YSBmb3IgQ3VycmVudCBNb250aH0KdGlkeU1vbnRoQ3JpbWVzMTggPC0gbW9udGhDcmltZXMxOCAlPiUgCiAgY3NfZmlsdGVyX2NvdW50KC4sIHZhciA9IGNvdW50KSAlPiUKICBjc19maWx0ZXJfY3JpbWUoLiwgdmFyID0gY3JpbWUsICJwYXJ0IDEiKSAlPiUKICBjc19jcmltZV9jYXQoLiwgdmFyID0gY3JpbWUsIGNyaW1lQ2F0TnVtLCAibnVtZXJpYyIpICU+JQogIGNzX2NyaW1lX2NhdCguLCB2YXIgPSBjcmltZSwgY3JpbWVDYXROYW1lLCAic3RyaW5nIikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHZpb2xlbnQsICJ2aW9sZW50IikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHByb3BlcnR5LCAicHJvcGVydHkiKSAlPiUKICBjc19wYXJzZV9kYXRlKC4sIGRhdGVfb2NjdXIsIGRhdGVWYXIgPSBkYXRlT2NjLCB0aW1lVmFyID0gdGltZU9jYykgJT4lCiAgZmlsdGVyKGRhdGVPY2MgPj0gYXMuRGF0ZSgiMjAxOC0wOC0wMSIpICYgZGF0ZU9jYyA8PSBhcy5EYXRlKCIyMDE4LTA4LTMxIikpICU+JQogIGZpbHRlcihkaXN0cmljdCA9PSAyIHwgZGlzdHJpY3QgPT0gNSkgJT4lCiAgbXV0YXRlKHdlZWtkYXkgPSB3ZGF5KGRhdGVPY2MsIGxhYmVsID0gVFJVRSkpICU+JQogIG11dGF0ZSh0b2QgPSB0aW1lT2NjKQoKdGlkeU1vbnRoQ3JpbWVzMTgkbmVpZ2hib3Job29kIDwtIGFzLm51bWVyaWModGlkeU1vbnRoQ3JpbWVzMTgkbmVpZ2hib3Job29kKQoKdGlkeU1vbnRoQ3JpbWVzMTgkdG9kIDwtIHN0cnB0aW1lKHRpZHlNb250aENyaW1lczE4JHRvZCwgdHogPSAiQW1lcmljYS9DaGljYWdvIiwgIiVIOiVNIikKdGlkeU1vbnRoQ3JpbWVzMTgkdG9kIDwtIGZvcm1hdCh0aWR5TW9udGhDcmltZXMxOCR0b2QsIGZvcm1hdCA9ICIlSCVNJVMiKQoKdGlkeU1vbnRoQ3JpbWVzMTggPC0gdGlkeU1vbnRoQ3JpbWVzMTggJT4lCiAgbXV0YXRlKC4sIGRheU5pZ2h0ID0gaWZlbHNlKHRvZCA+PSAiMTgwMDAwIiAmIHRvZCA8ICI2MDAwMDAiLCAiTmlnaHQiLCAiRGF5IikpICU+JSAKICBkcGx5cjo6c2VsZWN0KC1kYXRlVGltZSwgLXRvZCwgLWZsYWdfY3JpbWUsIC1mbGFnX2FkbWluaXN0cmF0aXZlLCAtZmxhZ191bmZvdW5kZWQsIC1mbGFnX2NsZWFudXApCgp0aWR5TW9udGhDcmltZXMxOCA8LSBjc19taXNzaW5nWFkodGlkeU1vbnRoQ3JpbWVzMTgsIHZhclggPSB4X2Nvb3JkLCB2YXJZID0geV9jb29yZCwgbmV3VmFyID0gbWlzc2luZykKdGFibGUodGlkeU1vbnRoQ3JpbWVzMTgkbWlzc2luZykKCnRpZHlNb250aENyaW1lczE4IDwtIHRpZHlNb250aENyaW1lczE4ICU+JSAKICBjc19yZXBsYWNlMCguLCB2YXIgPSB4X2Nvb3JkKSAlPiUKICBjc19yZXBsYWNlMCguLCB2YXIgPSB5X2Nvb3JkKSAlPiUgCiAgZmlsdGVyKC4sIG1pc3NpbmcgPT0gRkFMU0UpCmBgYAoKYGBge3IgVG90YWwgQ3JpbWVzIGZvciAyMDE4IFRpZGllZH0KdGlkeVRvdGFsQ3JpbWVzMTggPC0gdG90YWxDcmltZXMxOCAlPiUgCiAgY3NfZmlsdGVyX2NvdW50KC4sIHZhciA9IGNvdW50KSAlPiUKICBjc19maWx0ZXJfY3JpbWUoLiwgdmFyID0gY3JpbWUsICJwYXJ0IDEiKSAlPiUKICBjc19jcmltZV9jYXQoLiwgdmFyID0gY3JpbWUsIGNyaW1lQ2F0TnVtLCAibnVtZXJpYyIpICU+JQogIGNzX2NyaW1lX2NhdCguLCB2YXIgPSBjcmltZSwgY3JpbWVDYXROYW1lLCAic3RyaW5nIikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHZpb2xlbnQsICJ2aW9sZW50IikgJT4lCiAgY3NfY3JpbWUoLiwgdmFyID0gY3JpbWUsIHByb3BlcnR5LCAicHJvcGVydHkiKSAlPiUKICBjc19wYXJzZV9tb250aCguLCB2YXIgPSBjb2RlZF9tb250aCwgeWVhclZhciA9IHJlcG9ydFllYXIsIG1vbnRoID0gbW9udGhWYXIpICU+JQogIGNzX3BhcnNlX2RhdGUoLiwgZGF0ZV9vY2N1ciwgZGF0ZVZhciA9IGRhdGVPY2MsIHRpbWVWYXIgPSB0aW1lT2NjKSAlPiUKICBmaWx0ZXIoZGlzdHJpY3QgPT0gMiB8IGRpc3RyaWN0ID09IDUpICU+JQogIG11dGF0ZSh3ZWVrZGF5ID0gd2RheShkYXRlT2NjLCBsYWJlbCA9IFRSVUUpKSAlPiUKICBtdXRhdGUodG9kID0gdGltZU9jYykgCgp0aWR5VG90YWxDcmltZXMxOCRuZWlnaGJvcmhvb2QgPC0gYXMubnVtZXJpYyh0aWR5VG90YWxDcmltZXMxOCRuZWlnaGJvcmhvb2QpCgp0aWR5VG90YWxDcmltZXMxOCR0b2QgPC0gc3RycHRpbWUodGlkeVRvdGFsQ3JpbWVzMTgkdG9kLCB0eiA9ICJBbWVyaWNhL0NoaWNhZ28iLCAiJUg6JU0iKQp0aWR5VG90YWxDcmltZXMxOCR0b2QgPC0gZm9ybWF0KHRpZHlUb3RhbENyaW1lczE4JHRvZCwgZm9ybWF0ID0gIiVIJU0lUyIpCgp0aWR5VG90YWxDcmltZXMxOCA8LSB0aWR5VG90YWxDcmltZXMxOCAlPiUKICBtdXRhdGUoLiwgZGF5TmlnaHQgPSBpZmVsc2UodG9kID49ICIxODAwMDAiICYgdG9kIDwgIjYwMDAwMCIsICJOaWdodCIsICJEYXkiKSkgJT4lIAogIGRwbHlyOjpzZWxlY3QoLWRhdGVUaW1lLCAtdG9kLCAtZmxhZ19jcmltZSwgLWZsYWdfYWRtaW5pc3RyYXRpdmUsIC1mbGFnX3VuZm91bmRlZCwgLWZsYWdfY2xlYW51cCkKCnRpZHlUb3RhbENyaW1lczE4IDwtIGNzX21pc3NpbmdYWSh0aWR5VG90YWxDcmltZXMxOCwgdmFyWCA9IHhfY29vcmQsIHZhclkgPSB5X2Nvb3JkLCBuZXdWYXIgPSBtaXNzaW5nKQp0YWJsZSh0aWR5VG90YWxDcmltZXMxOCRtaXNzaW5nKQoKdGlkeVRvdGFsQ3JpbWVzMTggPC0gdGlkeVRvdGFsQ3JpbWVzMTggJT4lIAogIGNzX3JlcGxhY2UwKC4sIHZhciA9IHhfY29vcmQpICU+JQogIGNzX3JlcGxhY2UwKC4sIHZhciA9IHlfY29vcmQpICU+JSAKICBmaWx0ZXIoLiwgbWlzc2luZyA9PSBGQUxTRSkKCnJtKHRvdGFsQ3JpbWVzMTgpCmBgYAoKCiMjIyBDb21iaW5lIDIwMTggJiAyMDE5IAoKYGBge3IgSm9pbiBQcmV2aW91cyBZZWFycyBDcmltZXN9CmF1Z3VzdENyaW1lcyA8LSByYmluZCh0aWR5TW9udGhDcmltZXMxOCwgdGlkeUNyaW1lczE5KQpgYGAKCiMjIyBDcmVhdGUgU3BhdGlhbCBPYmplY3RzCgpgYGB7ciBDcmVhdGUgU0Ygb2JqZWN0cyBmb3IgMjAxOCAmIDIwMTkgQ3JpbWVzfQpjcmltZXNZZWFyMThfc2YgPC0gY3NfcHJvamVjdFhZKHRpZHlUb3RhbENyaW1lczE4LCB2YXJYID0geF9jb29yZCwgdmFyWSA9IHlfY29vcmQsIGNycyA9IDEwMjY5NikKY3JpbWVzMTlfc2YgPC0gY3NfcHJvamVjdFhZKHRpZHlDcmltZXMxOSwgdmFyWCA9IHhfY29vcmQsIHZhclkgPSB5X2Nvb3JkLCBjcnMgPSAxMDI2OTYpCmF1Z3VzdENyaW1lc19zZiA8LSBjc19wcm9qZWN0WFkoYXVndXN0Q3JpbWVzLCB2YXJYID0geF9jb29yZCwgdmFyWSA9IHlfY29vcmQsIGNycyA9IDEwMjY5NikKYGBgCgojIyMgUHJlcCBmb3IgRGF0YSBieSBOZWlnaGJvcmhvb2QKCmBgYHtyIE5laWdoYm9yaG9vZCBOdW1iZXIgTGlzdHN9CnNhIDwtIGMoMzksMjgsMzgsNTEsNTMsNTQsNTgsNDYsNDcsNDgsNDgpCmRzdDIgPC0gYyg3OjE1LDI3OjI5LCAzOTo0NSw4MSw4Miw4Nyw4OCkKZHN0NSA8LSBjKDM4LDQ2OjU4LDc4KQpgYGAKCiMjIE1hcHBpbmcgCgpPbmUgd2F5IHdlIHdvcmsgdG8gaW1wcm92ZSB0aGUgbGV2ZWwgb2YgcGh5c2ljYWwgJiBwZXJzb25hbCBzZWN1cml0eSBpcyB0aGUgYW5hbHlzaXMgYW5kIGRpc3RyaWJ1dGlvbiBvZiBjcmltZSBkYXRhIGFuZCBzdGF0aXN0aWNzLiBUaGUgb3JpZ2luYWwgc291cmNlIG9mIHRoaXMgY3JpbWUgZGF0YSBpcyA8aHR0cDovL3NsbXBkLm9yZy9jcmltZXJlcG9ydHMuc2h0bWw+LiBUaGlzIG5vdGVib29rIHRha2VzIHRoZSBkYXRhIHRoYXQgd2FzIHByZXZpb3VzbHkgY2xlYW5lZCBhbmQgbWFwcyB0aGUgZGF0YS4gIAoKIyMgTG9hZCBTcGF0aWFsIERhdGEgCgojIyMgQ29vcmRpbmF0ZXMKCmBgYHtyIFNlcnZpY2UgQXJlYSBOZWlnaGJvcmhvb2QgQ29vcmRpbmF0ZXN9Cnh5ZnBzZSA8LSBjKC05MC4yNjc5LCAtOTAuMjQyMywgMzguNjE3NiwgMzguNjMzNCkKeHljd2UgPC0gYygtOTAuMjc1OSwgLTkwLjIzNjgsIDM4LjYyODYsIDM4LjY1NTIpCnh5Ym90IDwtIGMoLTkwLjI2MTksIC05MC4yNDA5LCAzOC42MTY1LCAzOC42Mjk2KQp4eWRicCA8LSBjKC05MC4yODY5LCAtOTAuMjcyNiwgMzguNjQzMywgMzguNjU2NikKeHlzZGIgPC0gYygtOTAuMzAyNiwgLTkwLjI4MjcsIDM4LjY0NTYsIDM4LjY1NzEpCnh5d2UgPC0gYygtOTAuMzAyMCwgLTkwLjI3MTIsIDM4LjY1MTcsIDM4LjY3MTApCnh5dnAgPC0gYygtOTAuMjgwMywgLTkwLjI3MTIsIDM4LjY1MTcsIDM4LjY2MjIpCnh5YWMgPC0gYygtOTAuMjc0NCwgLTkwLjI2MDksIDM4LjY1MDUsIDM4LjY2NjEpCnh5ZnAgPC0gYygtOTAuMjY0OCwgLTkwLjI1NDMsIDM4LjY0OTMsIDM4LjY2NTUpCnh5bHAgPC0gYygtOTAuMjU4OCwgLTkwLjI0MzcsIDM4LjY0ODEsIDM4LjY2MjQpCnh5dmQgPC0gYygtOTAuMjUyMCwgLTkwLjIzMDQsIDM4LjY0MjYsIDM4LjY1ODUpCnh5bWMgPC0gYygtOTAuMjY3OCwgLTkwLjI1MTUsIDM4LjYzMDUsIDM4LjY0MTEpCnh5Y3R4IDwtIGMoLTkwLjI1ODEsIC05MC4yNDE5LCAzOC42Mjk5LCAzOC42Mzg2KQp4eWdydiA8LSBjKC05MC4yNjYyLCAtOTAuMjQ0MCwgMzguNjIzOCwgMzguNjMxOCkKeHlkc3QyIDwtIGMoLTkwLjMyMDMsIC05MC4yMjk3LCAzOC41NjEzLCAzOC42NDkzKQp4eWRzdDUgPC0gYygtOTAuMzA4MCwgLTkwLjIxMzIsIDM4LjYyNzMsIDM4LjY5NjIpCmBgYAoKCiMjIyBPcGVuIFN0cmVldCBNYXAgZnJvbSBNYXBib3ggLSBCYXNlbWFwIFRpbGUgSW1hZ2VyeQoKYGBge3IgT2J0YWluIEJhc2VtYXAgVGlsZXMsIGluY2x1ZGU9RkFMU0V9CmZwc2VfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHlmcHNlKSAlPiUKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpjd2VfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHljd2UpICU+JSAKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpib3RfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHlib3QpICU+JQogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCmRicF90aWxlcyA8LSByYXN0ZXI6OmV4dGVudCh4eWRicCkgJT4lIAogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCnNkYl90aWxlcyA8LSByYXN0ZXI6OmV4dGVudCh4eXNkYikgJT4lCiAgY2NfbG9jYXRpb24oLiwgdHlwZSA9ICJtYXBib3guc3RyZWV0cyIsIG1heF90aWxlcyA9IDE1KQoKd2VfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHl3ZSkgJT4lIAogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCnZwX3RpbGVzIDwtIHJhc3Rlcjo6ZXh0ZW50KHh5dnApICU+JQogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCmFjX3RpbGVzIDwtIHJhc3Rlcjo6ZXh0ZW50KHh5YWMpICU+JSAKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpmcF90aWxlcyA8LSByYXN0ZXI6OmV4dGVudCh4eWZwKSAlPiUgCiAgY2NfbG9jYXRpb24oLiwgdHlwZSA9ICJtYXBib3guc3RyZWV0cyIsIG1heF90aWxlcyA9IDE1KQoKbHBfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHlscCkgJT4lCiAgY2NfbG9jYXRpb24oLiwgdHlwZSA9ICJtYXBib3guc3RyZWV0cyIsIG1heF90aWxlcyA9IDE1KQoKdmRfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHl2ZCkgJT4lIAogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCm1jX3RpbGVzIDwtIHJhc3Rlcjo6ZXh0ZW50KHh5bWMpICU+JSAKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpjdHhfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHljdHgpICU+JSAKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpncnZfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHlncnYpICU+JSAKICBjY19sb2NhdGlvbiguLCB0eXBlID0gIm1hcGJveC5zdHJlZXRzIiwgbWF4X3RpbGVzID0gMTUpCgpkc3QyX3RpbGVzIDwtIHJhc3Rlcjo6ZXh0ZW50KHh5ZHN0MikgJT4lIAogIGNjX2xvY2F0aW9uKC4sIHR5cGUgPSAibWFwYm94LnN0cmVldHMiLCBtYXhfdGlsZXMgPSAxNSkKCmRzdDVfdGlsZXMgPC0gcmFzdGVyOjpleHRlbnQoeHlkc3Q1KSAlPiUgCiAgY2NfbG9jYXRpb24oLiwgdHlwZSA9ICJtYXBib3guc3RyZWV0cyIsIG1heF90aWxlcyA9IDE1KQoKcm0oeHlmcHNlLCB4eWN3ZSwgeHlib3QsIHh5ZGJwLCB4eXNkYiwgeHl3ZSwgeHl2cCwgeHlhYywgeHlmcCwgeHlscCwgeHl2ZCwgeHltYywgeHljdHgsIHh5Z3J2LCB4eWRzdDIsIHh5ZHN0NSkKYGBgCgojIyMgTG9hZCBFeHRlcm5hbCBEYXRhCgojIyMjIFBvcHVsYXRpb24gRGF0YSAKCmBgYHtyfQpsb2FkKGhlcmUoImRhdGEvbmJoZF9wb3AxMC5yZGEiKSkKYGBgCgoKIyMjIyBTcGF0aWFsIAoKYGBge3IgbG9hZCBzaGFwZWZpbGVzLCBpbmNsdWRlPUZBTFNFfQpzdF9yZWFkKGhlcmUoImRhdGEiLCAiZXh0ZXJuYWwiLCAibWVkLWNhbXB1cyIsICJtZWRjYW1wdXMuc2hwIikpICU+JQogIHN0X3RyYW5zZm9ybShjcnMgPSAxMDI2OTYpIC0+IG1lZF9jYW1wdXMKCnN0X3JlYWQoaGVyZSgiZGF0YSIsICJleHRlcm5hbCIsICJjb3J0ZXgtYm91bmRhcnkiLCAiQ09SVEVYIEJPVU5EQVJZLnNocCIpKSAlPiUKICBzdF90cmFuc2Zvcm0oY3JzID0gMTAyNjk2KSAtPiBjb3J0ZXgKCnN0X3JlYWQoaGVyZSgiZGF0YSIsICJleHRlcm5hbCIsICJncm92ZS1jaWQiLCAiZ3JvdmVjaWQuc2hwIikpICU+JQogIHN0X3RyYW5zZm9ybShjcnMgPSAxMDI2OTYpIC0+IGdyb3ZlX2NpZAoKc3RfcmVhZChoZXJlKCJkYXRhIiwgImV4dGVybmFsIiwgInN0bF9uZWlnaGJvcmhvb2RzIiwgIm5iaGRzLnNocCIpKSAlPiUKICBzdF90cmFuc2Zvcm0oY3JzID0gMTAyNjk2KSAlPiUgCiAgcmVuYW1lKC4sICJuZWlnaGJvcmhvb2QiID0gTkhEX05VTSktPiBuaG9vZHNfc2YKCmZwc2UgPC0gZmlsdGVyKG5ob29kc19zZiwgbmVpZ2hib3Job29kID09IDM5ICkKY3dlIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSAzOCApCmJvdCA8LSBmaWx0ZXIobmhvb2RzX3NmLCBuZWlnaGJvcmhvb2QgPT0gMjggKQpkYnAgPC0gZmlsdGVyKG5ob29kc19zZiwgbmVpZ2hib3Job29kID09IDQ3ICkKc2RiIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA0NiApCndlIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA0OCApCnZwIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA0OSApCmFjIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA1MSApCmZwIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA1MyApCmxwIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA1NCApCnZkIDwtIGZpbHRlcihuaG9vZHNfc2YsIG5laWdoYm9yaG9vZCA9PSA1OCApCmBgYAoKIyMjIENvbWJpbmUgUG9wdWxhdGlvbiAmIE5laWdoYm9yaG9vZCBTcGF0aWFsIERhdGEgYnkgUG9saWNlIERpc3RyaWN0CgojIyMjIE9nYW5pemUgJiBGaWx0ZXIgQ3JpbWUgRGF0YSBieSBOZWlnaGJvcmhvb2QgCgpgYGB7ciBDcmltZSBSYXRlcyAtIERpc3RyaWN0IDJ9CmRzdF8yIDwtIHRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCAlaW4lIGRzdDIpICU+JSAKICBncm91cF9ieSguLCBuZWlnaGJvcmhvb2QpICU+JQogIGNvdW50KCkgJT4lIAogIHJlbmFtZShjcmltZVRvdGFsID0gbikgJT4lCiAgbGVmdF9qb2luKG5iaGRfcG9wMTAsIGJ5ID0gIm5laWdoYm9yaG9vZCIpICU+JSAKICBtdXRhdGUoLiwgY3JpbWVSYXRlID0gKGNyaW1lVG90YWwvcG9wMTApKjEwMDApICU+JSAKICBkcm9wX25hKCkKYGBgCgpgYGB7ciBDcmltZSBSYXRlcyAtIERpc3RyaWN0IDV9CmRzdF81IDwtIHRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCAlaW4lIGRzdDUpICU+JSAKICBncm91cF9ieSguLCBuZWlnaGJvcmhvb2QpICU+JQogIGNvdW50KCkgJT4lIAogIHJlbmFtZShjcmltZVRvdGFsID0gbikgJT4lCiAgbGVmdF9qb2luKG5iaGRfcG9wMTAsIGJ5ID0gIm5laWdoYm9yaG9vZCIpICU+JSAKICBtdXRhdGUoLiwgY3JpbWVSYXRlID0gKGNyaW1lVG90YWwvcG9wMTApKjEwMDApICU+JSAKICBkcm9wX25hKCkKYGBgCgpgYGB7ciBKb2luIFJhdGVzICYgTmVpZ2hib3Job29kcyAtIERpc3RyaWN0IDJ9CmRzdF8yX3BvcCA8LSBsZWZ0X2pvaW4obmhvb2RzX3NmLCBkc3RfMiwgYnkgPSAibmVpZ2hib3Job29kIikgJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSAxMDI2OTYpICU+JQogIGRyb3BfbmEoKSAlPiUgCiAgc3Vic2V0KC4sIG5laWdoYm9yaG9vZCAhPSA4OCkKYGBgCgpgYGB7ciBKb2luIFJhdGVzICYgTmVpZ2hib3Job29kcyAtIERpc3RyaWN0IDV9CmRzdF81X3BvcCA8LSBsZWZ0X2pvaW4obmhvb2RzX3NmLCBkc3RfNSwgYnkgPSAibmVpZ2hib3Job29kIikgJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSAxMDI2OTYpICU+JQogIGRyb3BfbmEoKQpgYGAKCgojIyMgRlBTRSwgQk9ULCBDV0UsIE1DIAoKIyMjIyBNYXAgQ3JlYXRpb24KCiMjIyMjIEZQU0UKCmBgYHtyIEZQU0UgVG90YWwgQ3JpbWV9CmZwc2VfdG90YWxfdG0gPC0gdG1fc2hhcGUoZnBzZV90aWxlcykgKwogIHRtX3JnYigpICsKICBuaG9vZHNfc2YgJT4lCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOSkgJT4lIAogIHRtX3NoYXBlKCkgKwogICAgdG1fZmlsbChjb2wgPSAiIzllY2FlMSIsIAogICAgICAgICAgICBhbHBoYSA9IC41KSArCiAgICB0bV9ib3JkZXJzKGNvbCA9ICJibGFjayIsIAogICAgICAgICAgICAgICBsd2QgPSAyLCAKICAgICAgICAgICAgICAgbHR5ID0gImRhc2hlZCIpICsKICBmaWx0ZXIoY3JpbWVzMTlfc2YsIAogICAgICAgICBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JQogIHRtX3NoYXBlKCkgKwogICAgdG1fYnViYmxlcyhzaXplID0gLjI1LCAKICAgICAgICAgICAgICAgY29sID0gImNyaW1lQ2F0TmFtZSIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIlNldDEiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlBhcnQgMSBDcmltZXMiKSArCiAgdG1fY3JlZGl0cygiwqkgTWFwYm94LCDCqSBPcGVuU3RyZWV0TWFwIiwgcG9zaXRpb24gPSBjKCJsZWZ0IiwgIkJPVFRPTSIpKSArCiAgdG1fbGF5b3V0KAogICAgbWFpbi50aXRsZSA9ICJGUFNFIFRvdGFsIENyaW1lIC0gQXVndXN0IDIwMTkiLAogICAgZnJhbWUgPSBGQUxTRSwKICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsIAogICAgbGVnZW5kLmZyYW1lPVRSVUUsCiAgICBsZWdlbmQub3V0c2lkZSA9IFRSVUUsCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgCgpmcHNlX3RvdGFsX3RtCmBgYCAKCgpgYGB7ciBGUFNFIERheSAmIE5pZ2h0fQpmcHNlX2RuX3RtIDwtIHRtX3NoYXBlKGZwc2VfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgbmhvb2RzX3NmICU+JQogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICB0bV9zaGFwZSgpICsKICAgIHRtX2ZpbGwoY29sID0gIiM5ZWNhZTEiLCAKICAgICAgICAgICAgYWxwaGEgPSAuNSkgKwogICAgdG1fYm9yZGVycyhjb2wgPSAiYmxhY2siLCAKICAgICAgICAgICAgICAgbHdkID0gMiwgCiAgICAgICAgICAgICAgIGx0eSA9ICJkYXNoZWQiKSArCiAgZmlsdGVyKGNyaW1lczE5X3NmLCAKICAgICAgICAgbmVpZ2hib3Job29kID09IDM5KSAlPiUKICB0bV9zaGFwZSgpICsKICAgIHRtX2J1YmJsZXMoc2l6ZSA9IC4yNSwgCiAgICAgICAgICAgICAgIGNvbCA9ICJkYXlOaWdodCIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIi1SZEJ1IiwgCiAgICAgICAgICAgICAgIHRpdGxlLmNvbCA9ICJUaW1lIG9mIENyaW1lcyIpICsKICB0bV9jcmVkaXRzKCLCqSBNYXBib3gsIMKpIE9wZW5TdHJlZXRNYXAiLCBwb3NpdGlvbiA9IGMoImxlZnQiLCAiQk9UVE9NIikpICsKICB0bV9sYXlvdXQoCiAgICBtYWluLnRpdGxlID0gIkZQU0UgVGltZSBvZiBDcmltZXMgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmZwc2VfZG5fdG0KYGBgCgpgYGB7ciBGUFNFIENyaW1lcyBBZ2FpbnN0IFBlcnNvbnN9CmZwc2VfdmxudF90bSA8LSB0bV9zaGFwZShmcHNlX3RpbGVzKSArCiAgdG1fcmdiKCkgKwogIG5ob29kc19zZiAlPiUKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM5KSAlPiUgCiAgdG1fc2hhcGUoKSArCiAgICB0bV9maWxsKGNvbCA9ICIjOWVjYWUxIiwgCiAgICAgICAgICAgIGFscGhhID0gLjUpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIGZpbHRlcihjcmltZXMxOV9zZiwgCiAgICAgICAgIG5laWdoYm9yaG9vZCA9PSAzOSkgJT4lCiAgdG1fc2hhcGUoKSArCiAgICB0bV9idWJibGVzKHNpemUgPSAuMjUsIAogICAgICAgICAgICAgICBjb2wgPSAidmlvbGVudCIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIlJlZHMiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlZpb2xlbnQiKSArCiAgdG1fY3JlZGl0cygiwqkgTWFwYm94LCDCqSBPcGVuU3RyZWV0TWFwIiwgcG9zaXRpb24gPSBjKCJsZWZ0IiwgIkJPVFRPTSIpKSArCiAgdG1fbGF5b3V0KAogICAgbWFpbi50aXRsZSA9ICJGUFNFIFZpb2xlbnQgQ3JpbWUgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmZwc2VfdmxudF90bQpgYGAKCmBgYHtyIEZQU0UgRGVuc2l0eSBNYXAgU0Z9CmNyaW1lczE5X3NmICU+JQogIGZpbHRlcihuZWlnaGJvcmhvb2QgPT0gMzkpICU+JQogIHNtb290aF9tYXAoLiwgYmFuZHdpZHRoID0gMC41LCBzdHlsZSA9ICJwcmV0dHkiLAogIGNvdmVyID0gZnBzZSkgLT4gZnBzZV9kZW5zaXRpZXMKYGBgCgoKYGBge3IgRlBTRSBEZW5zaXR5IE1hcCBPdXRwdXR9CmZwc2VfZGVuX3RtIDwtIHRtX3NoYXBlKGZwc2VfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgbmhvb2RzX3NmICU+JQogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICB0bV9zaGFwZSgpICsKICAgIHRtX2ZpbGwoY29sID0gTkEsIAogICAgICAgICAgICBhbHBoYSA9IC41KSArCiAgICB0bV9ib3JkZXJzKGNvbCA9ICJibGFjayIsIAogICAgICAgICAgICAgICBsd2QgPSAyLCAKICAgICAgICAgICAgICAgbHR5ID0gImRhc2hlZCIpICsKICB0bV9zaGFwZShmcHNlX2RlbnNpdGllcyRwb2x5Z29ucykgKwogIHRtX2ZpbGwoY29sID0gImxldmVsIiwgcGFsZXR0ZSA9ICJCdVB1IiwgYWxwaGEgPSAuNjAsIAogICAgdGl0bGUgPSBleHByZXNzaW9uKCJDcmltZXMgcGVyICIgKiBrbV4yKSkgKwogIHRtX2NyZWRpdHMoIsKpIE1hcGJveCwgwqkgT3BlblN0cmVldE1hcCIsIHBvc2l0aW9uID0gYygibGVmdCIsICJCT1RUT00iKSkgKwogIHRtX2xheW91dCgKICAgIG1haW4udGl0bGUgPSAiRlBTRSBDcmltZSBEZW5zaXR5IC0gQXVndXN0IDIwMTkiLAogICAgZnJhbWUgPSBGQUxTRSwKICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsIAogICAgbGVnZW5kLmZyYW1lPVRSVUUsCiAgICBsZWdlbmQub3V0c2lkZSA9IFRSVUUsCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgCgpmcHNlX2Rlbl90bQpgYGAKIyMjIyMjIEdyb3ZlIENJRCAKCmBgYHtyIEdyb3ZlIENJRCBUb3RhbCBDcmltZX0KZ3JvdmVfY3JpbWVzIDwtIHN0X2ludGVyc2VjdGlvbihjcmltZXMxOV9zZiwgZ3JvdmVfY2lkKQoKZnBzZV9ncm92ZV90bSA8LSB0bV9zaGFwZShncnZfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgbmhvb2RzX3NmICU+JQogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICB0bV9zaGFwZSgpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIHRtX3NoYXBlKGdyb3ZlX2NpZCkgKwogICAgdG1fZmlsbChjb2wgPSAiIzllY2FlMSIsIAogICAgICAgICAgICBhbHBoYSA9IC41KSArCiAgICB0bV9ib3JkZXJzKGNvbCA9ICJibGFjayIsIAogICAgICAgICAgICAgICBsd2QgPSAxLCAKICAgICAgICAgICAgICAgbHR5ID0gInNvbGlkIikgKwogIHRtX3NoYXBlKGdyb3ZlX2NyaW1lcykgKwogICAgdG1fYnViYmxlcyhzaXplID0gLjI1LCAKICAgICAgICAgICAgICAgY29sID0gImNyaW1lQ2F0TmFtZSIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIlNldDEiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlBhcnQgMSBDcmltZXMiKSArCiAgdG1fY3JlZGl0cygiwqkgTWFwYm94LCDCqSBPcGVuU3RyZWV0TWFwIiwgcG9zaXRpb24gPSBjKCJsZWZ0IiwgIkJPVFRPTSIpKSArCiAgdG1fbGF5b3V0KAogICAgbWFpbi50aXRsZSA9ICJHcm92ZSBDSUQgVG90YWwgQ3JpbWUgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmZwc2VfZ3JvdmVfdG0KYGBgCgojIyMjIyBDV0UKCgpgYGB7ciBDV0UgVG90YWwgQ3JpbWV9CmN3ZV90b3RhbF90bSA8LSB0bV9zaGFwZShjd2VfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgbmhvb2RzX3NmICU+JQogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICB0bV9zaGFwZSgpICsKICAgIHRtX2ZpbGwoY29sID0gIiM5ZWNhZTEiLCAKICAgICAgICAgICAgYWxwaGEgPSAuNSkgKwogICAgdG1fYm9yZGVycyhjb2wgPSAiYmxhY2siLCAKICAgICAgICAgICAgICAgbHdkID0gMiwgCiAgICAgICAgICAgICAgIGx0eSA9ICJkYXNoZWQiKSArCiAgZmlsdGVyKGNyaW1lczE5X3NmLCAKICAgICAgICAgbmVpZ2hib3Job29kID09IDM4KSAlPiUKICB0bV9zaGFwZSgpICsKICAgIHRtX2J1YmJsZXMoc2l6ZSA9IC4yNSwgCiAgICAgICAgICAgICAgIGNvbCA9ICJjcmltZUNhdE5hbWUiLCAKICAgICAgICAgICAgICAgcGFsZXR0ZSA9ICJTZXQxIiwgCiAgICAgICAgICAgICAgIHRpdGxlLmNvbCA9ICJQYXJ0IDEgQ3JpbWVzIikgKwogIHRtX2NyZWRpdHMoIsKpIE1hcGJveCwgwqkgT3BlblN0cmVldE1hcCIsIHBvc2l0aW9uID0gYygibGVmdCIsICJCT1RUT00iKSkgKwogIHRtX2xheW91dCgKICAgIG1haW4udGl0bGUgPSAiQ1dFIFRvdGFsIENyaW1lIC0gQXVndXN0IDIwMTkiLAogICAgZnJhbWUgPSBGQUxTRSwKICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsIAogICAgbGVnZW5kLmZyYW1lPVRSVUUsCiAgICBsZWdlbmQub3V0c2lkZSA9IFRSVUUsCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgCgpjd2VfdG90YWxfdG0KYGBgIAoKCmBgYHtyIGN3ZSBEYXkgJiBOaWdodH0KY3dlX2RuX3RtIDwtIHRtX3NoYXBlKGN3ZV90aWxlcykgKwogIHRtX3JnYigpICsKICBuaG9vZHNfc2YgJT4lCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOCkgJT4lIAogIHRtX3NoYXBlKCkgKwogICAgdG1fZmlsbChjb2wgPSAiIzllY2FlMSIsIAogICAgICAgICAgICBhbHBoYSA9IC41KSArCiAgICB0bV9ib3JkZXJzKGNvbCA9ICJibGFjayIsIAogICAgICAgICAgICAgICBsd2QgPSAyLCAKICAgICAgICAgICAgICAgbHR5ID0gImRhc2hlZCIpICsKICBmaWx0ZXIoY3JpbWVzMTlfc2YsIAogICAgICAgICBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JQogIHRtX3NoYXBlKCkgKwogICAgdG1fYnViYmxlcyhzaXplID0gLjI1LCAKICAgICAgICAgICAgICAgY29sID0gImRheU5pZ2h0IiwgCiAgICAgICAgICAgICAgIHBhbGV0dGUgPSAiLVJkQnUiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlRpbWUgb2YgQ3JpbWVzIikgKwogIHRtX2NyZWRpdHMoIsKpIE1hcGJveCwgwqkgT3BlblN0cmVldE1hcCIsIHBvc2l0aW9uID0gYygibGVmdCIsICJCT1RUT00iKSkgKwogIHRtX2xheW91dCgKICAgIG1haW4udGl0bGUgPSAiQ1dFIFRvdGFsIENyaW1lIC0gQXVndXN0IDIwMTkiLAogICAgZnJhbWUgPSBGQUxTRSwKICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsIAogICAgbGVnZW5kLmZyYW1lPVRSVUUsCiAgICBsZWdlbmQub3V0c2lkZSA9IFRSVUUsCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgCgpjd2VfZG5fdG0KYGBgCgpgYGB7ciBDV0UgQ3JpbWVzIEFnYWluc3QgUGVyc29uc30KY3dlX3ZsbnRfdG0gPC0gdG1fc2hhcGUoY3dlX3RpbGVzKSArCiAgdG1fcmdiKCkgKwogIG5ob29kc19zZiAlPiUKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM4KSAlPiUgCiAgdG1fc2hhcGUoKSArCiAgICB0bV9maWxsKGNvbCA9ICIjOWVjYWUxIiwgCiAgICAgICAgICAgIGFscGhhID0gLjUpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIGZpbHRlcihjcmltZXMxOV9zZiwgCiAgICAgICAgIG5laWdoYm9yaG9vZCA9PSAzOCkgJT4lCiAgdG1fc2hhcGUoKSArCiAgICB0bV9idWJibGVzKHNpemUgPSAuMjUsIAogICAgICAgICAgICAgICBjb2wgPSAidmlvbGVudCIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIlJlZHMiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlZpb2xlbnQiKSArCiAgdG1fY3JlZGl0cygiwqkgTWFwYm94LCDCqSBPcGVuU3RyZWV0TWFwIiwgcG9zaXRpb24gPSBjKCJsZWZ0IiwgIkJPVFRPTSIpKSArCiAgdG1fbGF5b3V0KAogICAgbWFpbi50aXRsZSA9ICJDV0UgVGltZSBvZiBDcmltZXMgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmN3ZV92bG50X3RtCmBgYAoKYGBge3IgQ1dFIERlbnNpdHkgTWFwIFNGfQpjd2VfZGVuc2l0aWVzIDwtIGNyaW1lczE5X3NmICU+JQogIGZpbHRlcihuZWlnaGJvcmhvb2QgPT0gMzgpICU+JQogIHNtb290aF9tYXAoLiwgYmFuZHdpZHRoID0gMC41LCBzdHlsZSA9ICJwcmV0dHkiLAogIGNvdmVyID0gY3dlKQpgYGAKCgpgYGB7ciBDV0UgRGVuc2l0eSBNYXAgT3V0cHV0fQpjd2VfZGVuX3RtIDwtIHRtX3NoYXBlKGN3ZV90aWxlcykgKwogIHRtX3JnYigpICsKICBuaG9vZHNfc2YgJT4lCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOCkgJT4lIAogIHRtX3NoYXBlKCkgKwogICAgdG1fZmlsbChjb2wgPSBOQSwgCiAgICAgICAgICAgIGFscGhhID0gLjUpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIHRtX3NoYXBlKGN3ZV9kZW5zaXRpZXMkcG9seWdvbnMpICsKICB0bV9maWxsKGNvbCA9ICJsZXZlbCIsIHBhbGV0dGUgPSAiQnVQdSIsIGFscGhhID0gLjYwLCAKICAgIHRpdGxlID0gZXhwcmVzc2lvbigiQ3JpbWVzIHBlciAiICoga21eMikpICsKICB0bV9jcmVkaXRzKCLCqSBNYXBib3gsIMKpIE9wZW5TdHJlZXRNYXAiLCBwb3NpdGlvbiA9IGMoImxlZnQiLCAiQk9UVE9NIikpICsKICB0bV9sYXlvdXQoCiAgICBtYWluLnRpdGxlID0gIkNXRSBDcmltZSBEZW5zaXR5LSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmN3ZV9kZW5fdG0KYGBgCiMjIyMjIyBNZWRpY2FsIENhbXB1cwoKYGBge3IgTWVkaWNhbCBDYW1wdXMgVG90YWwgQ3JpbWUgMjAxOX0KbWNfY3JpbWVzIDwtIHN0X2ludGVyc2VjdGlvbihjcmltZXMxOV9zZiwgbWVkX2NhbXB1cykKCgpjd2VfbWNfdG0gPC0gdG1fc2hhcGUobWNfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgbmhvb2RzX3NmICU+JQogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICB0bV9zaGFwZSgpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIHRtX3NoYXBlKG1lZF9jYW1wdXMpICsKICAgIHRtX2ZpbGwoY29sID0gIiM5ZWNhZTEiLCAKICAgICAgICAgICAgYWxwaGEgPSAuNSkgKwogICAgdG1fYm9yZGVycyhjb2wgPSAiYmxhY2siLCAKICAgICAgICAgICAgICAgbHdkID0gMSwgCiAgICAgICAgICAgICAgIGx0eSA9ICJzb2xpZCIpICsKICB0bV9zaGFwZShtY19jcmltZXMpICsKICAgIHRtX2J1YmJsZXMoc2l6ZSA9IC4yNSwgCiAgICAgICAgICAgICAgIGNvbCA9ICJjcmltZUNhdE5hbWUiLCAKICAgICAgICAgICAgICAgcGFsZXR0ZSA9ICJTZXQxIiwgCiAgICAgICAgICAgICAgIHRpdGxlLmNvbCA9ICJQYXJ0IDEgQ3JpbWVzIikgKwogIHRtX2NyZWRpdHMoIsKpIE1hcGJveCwgwqkgT3BlblN0cmVldE1hcCIsIHBvc2l0aW9uID0gYygibGVmdCIsICJCT1RUT00iKSkgKwogIHRtX2xheW91dCgKICAgIG1haW4udGl0bGUgPSAiTWVkLiBDYW1wdXMgVG90YWwgQ3JpbWUgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmN3ZV9tY190bQoKbWNfY3JpbWVzXzE4IDwtIHN0X2ludGVyc2VjdGlvbihjcmltZXNZZWFyMThfc2YsIG1lZF9jYW1wdXMpICU+JSAKICBhcy5kYXRhLmZyYW1lKCkKCm1jX2NyaW1lcyA8LSBtY19jcmltZXMgJT4lIAogICBhcy5kYXRhLmZyYW1lKCkKCm1jX2NyaW1lc18xOCAlPiUgCiAgZ3JvdXBfYnkobW9udGhWYXIpICU+JSAKICBjb3VudChjcmltZUNhdE5hbWUpICU+JSAKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbikgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBtb250aFZhciwgdmFsdWVzX2Zyb20gPSAiTnVtYmVyIG9mIENyaW1lcyIpICU+JSAKICByZXBsYWNlKC4sIGlzLm5hKC4pLCAwKSAlPiUgCiAgcmVuYW1lKC4sICJQYXJ0IDEgQ3JpbWVzIiA9IGNyaW1lQ2F0TmFtZSwgCiAgICAgICAgICJKYW51YXJ5IiA9ICIwMSIsCiAgICAgICAgICJGZWJydWFyeSIgPSAiMDIiLAogICAgICAgICAiTWFyY2giID0gIjAzIiwKICAgICAgICAgIkFwcmlsIiA9ICIwNCIsCiAgICAgICAgICJNYXkiID0gIjA1IiwKICAgICAgICAgIkp1bmUiID0gIjA2IiwKICAgICAgICAgIkp1bHkiID0gIjA3IiwKICAgICAgICAgIkF1Z3VzdCIgPSAiMDgiLAogICAgICAgICAiU2VwdGVtYmVyIiA9ICIwOSIsCiAgICAgICAgICJPY3RvYmVyIiA9ICIxMCIsCiAgICAgICAgICJOb3ZlbWJlciIgPSAiMTEiLAogICAgICAgICAiRGVjZW1iZXIiID0gIjEyIikgJT4lIAogIGFkb3JuX3RvdGFscyguLCAiY29sIiwgbmFtZSA9ICJUb3RhbCIpICU+JSAKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAtPiBtY18yMDE4CgptY19jcmltZXMgJT4lIAogIGdyb3VwX2J5KGNyaW1lQ2F0TmFtZSkgJT4lIAogIGNvdW50KCkgJT4lIAogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiUGFydCAxIENyaW1lcyIgPSBjcmltZUNhdE5hbWUpIC0+IG1jX2NyaW1lQ2F0CgprYWJsZShtY19jcmltZUNhdCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJtY19jcmltQ2F0LmpwZWciKQoKbWNfY3JpbWVzICU+JSAKICBncm91cF9ieShkYXlOaWdodCkgJT4lIAogIGNvdW50KCkgJT4lCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJUaW1lIG9mIERheSIgPSBkYXlOaWdodCkgLT4gbWNfZGF5TmlnaHQKCmthYmxlKG1jX2RheU5pZ2h0KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoIm1jX2RheU5pZ2h0LmpwZWciKQoKbWNfbGFyY2VuaWVzIDwtIG1jX2NyaW1lcyAlPiUgCiAgZmlsdGVyKC4sIGNyaW1lQ2F0TnVtID09IDYpCgp3cml0ZS5jc3YobWNfbGFyY2VuaWVzLCBmaWxlID0gaGVyZSgicmVzdWx0cy9jd2UvMjAxOS9hdWd1c3QvY3dlX2xhcmNlbmllcy5jc3YiKSkKCndyaXRlLmNzdihtY19jcmltZXMsIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2N3ZS8yMDE5L2F1Z3VzdC9tY19jcmltZXNfYXVndXN0MTkuY3N2IikpCndyaXRlLmNzdihtY18yMDE4LCBmaWxlID0gaGVyZSgicmVzdWx0cy9jd2UvMjAxOS9hdWd1c3QvbWNfY3JpbWVzXzIwMTguY3N2IikpCgpgYGAKCgoKIyMjIyMjIENvcnRleAoKYGBge3IgQ29ydGV4IFRvdGFsIENyaW1lfQpjdHhfY3JpbWVzIDwtIHN0X2ludGVyc2VjdGlvbihjcmltZXMxOV9zZiwgY29ydGV4KQoKY3dlX2N0eF90bSA8LSB0bV9zaGFwZShjdHhfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgbmhvb2RzX3NmICU+JQogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICB0bV9zaGFwZSgpICsKICAgIHRtX2JvcmRlcnMoY29sID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIGx3ZCA9IDIsIAogICAgICAgICAgICAgICBsdHkgPSAiZGFzaGVkIikgKwogIHRtX3NoYXBlKGNvcnRleCkgKwogICAgdG1fZmlsbChjb2wgPSAiIzllY2FlMSIsIAogICAgICAgICAgICBhbHBoYSA9IC41KSArCiAgICB0bV9ib3JkZXJzKGNvbCA9ICJibGFjayIsIAogICAgICAgICAgICAgICBsd2QgPSAxLCAKICAgICAgICAgICAgICAgbHR5ID0gInNvbGlkIikgKwogIHRtX3NoYXBlKGN0eF9jcmltZXMpICsKICAgIHRtX2J1YmJsZXMoc2l6ZSA9IC4yNSwgCiAgICAgICAgICAgICAgIGNvbCA9ICJjcmltZUNhdE5hbWUiLCAKICAgICAgICAgICAgICAgcGFsZXR0ZSA9ICJTZXQxIiwgCiAgICAgICAgICAgICAgIHRpdGxlLmNvbCA9ICJQYXJ0IDEgQ3JpbWVzIikgKwogIHRtX2NyZWRpdHMoIsKpIE1hcGJveCwgwqkgT3BlblN0cmVldE1hcCIsIHBvc2l0aW9uID0gYygibGVmdCIsICJCT1RUT00iKSkgKwogIHRtX2xheW91dCgKICAgIG1haW4udGl0bGUgPSAiQ29ydGV4IFRvdGFsIENyaW1lIC0gQXVndXN0IDIwMTkiLAogICAgZnJhbWUgPSBGQUxTRSwKICAgIGxlZ2VuZC5iZy5jb2xvciA9ICJ3aGl0ZSIsIAogICAgbGVnZW5kLmZyYW1lPVRSVUUsCiAgICBsZWdlbmQub3V0c2lkZSA9IFRSVUUsCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKCJyaWdodCIsICJib3R0b20iKSkgCgpjd2VfY3R4X3RtCmBgYAoKCiMjIyMjIEJvdGFuaWNhbCBIZWlnaHRzCgpgYGB7ciBCb3RhbmljYWwgSGVpZ2h0cyBUb3RhbCBDcmltZX0KYm90X3RvdGFsX3RtIDwtIHRtX3NoYXBlKGJvdF90aWxlcykgKwogIHRtX3JnYigpICsKICBuaG9vZHNfc2YgJT4lCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAyOCkgJT4lIAogIHRtX3NoYXBlKCkgKwogICAgdG1fZmlsbChjb2wgPSAiIzllY2FlMSIsIAogICAgICAgICAgICBhbHBoYSA9IC41KSArCiAgICB0bV9ib3JkZXJzKGNvbCA9ICJibGFjayIsIAogICAgICAgICAgICAgICBsd2QgPSAyLCAKICAgICAgICAgICAgICAgbHR5ID0gImRhc2hlZCIpICsKICBmaWx0ZXIoY3JpbWVzMTlfc2YsIAogICAgICAgICBuZWlnaGJvcmhvb2QgPT0gMjgpICU+JQogIHRtX3NoYXBlKCkgKwogICAgdG1fYnViYmxlcyhzaXplID0gLjI1LCAKICAgICAgICAgICAgICAgY29sID0gImNyaW1lQ2F0TmFtZSIsIAogICAgICAgICAgICAgICBwYWxldHRlID0gIlNldDEiLCAKICAgICAgICAgICAgICAgdGl0bGUuY29sID0gIlBhcnQgMSBDcmltZXMiKSArCiAgdG1fY3JlZGl0cygiwqkgTWFwYm94LCDCqSBPcGVuU3RyZWV0TWFwIiwgcG9zaXRpb24gPSBjKCJsZWZ0IiwgIkJPVFRPTSIpKSArCiAgdG1fbGF5b3V0KAogICAgbWFpbi50aXRsZSA9ICJCb3RhbmljYWwgSGVpZ2h0cyBUb3RhbCBDcmltZSAtIEF1Z3VzdCAyMDE5IiwKICAgIGZyYW1lID0gRkFMU0UsCiAgICBsZWdlbmQuYmcuY29sb3IgPSAid2hpdGUiLCAKICAgIGxlZ2VuZC5mcmFtZT1UUlVFLAogICAgbGVnZW5kLm91dHNpZGUgPSBUUlVFLAogICAgbGVnZW5kLnBvc2l0aW9uID0gYygicmlnaHQiLCAiYm90dG9tIikpIAoKYm90X3RvdGFsX3RtCmBgYAoKCiMjIyMjIERpc3RyaWN0IDIgRGVuc2l0eSBNYXBzCmBgYHtyIEdlbmVyYXRlIERpc3RyaWN0IDIgRGVuc2l0eSBNYXBzfQpkc3QyX3JhdGVNYXAgPC0gdG1fc2hhcGUoZHN0Ml90aWxlcykgKwogIHRtX3JnYigpICsKICB0bV9zaGFwZShkc3RfMl9wb3ApICsKICB0bV9wb2x5Z29ucyhjb2wgPSAiY3JpbWVSYXRlIiwKICAgICAgICAgICAgICBwYWxldHRlID0gIkJ1UHUiLAogICAgICAgICAgICAgIHN0eWxlID0gImplbmtzIiwKICAgICAgICAgICAgICB0aXRsZSA9ICJDcmltZXMgcGVyIDEsMDAwIFJlc2lkZW50cyIpICsKICB0bV90ZXh0KCJuZWlnaGJvcmhvb2QiLCBzaGFkb3c9VFJVRSkgKwogIHRtX2xheW91dCgKICAgIG1haW4udGl0bGUgPSAiRGlzdHJpY3QgMiBDcmltZSBSYXRlcyAtIEF1Z3VzdCAyMDE5IiwKICAgIGZyYW1lID0gRkFMU0UsCiAgICBsZWdlbmQuYmcuY29sb3IgPSAid2hpdGUiLCAKICAgIGxlZ2VuZC5mcmFtZT1UUlVFLAogICAgbGVnZW5kLm91dHNpZGUgPSBUUlVFLAogICAgbGVnZW5kLnBvc2l0aW9uID0gYygicmlnaHQiLCAiYm90dG9tIikpIAoKZHN0Ml9yYXRlTWFwCgoKYGBgCgpgYGB7cn0KZHN0XzJfc3RhdHNUb3RhbCA8LSBkZXNjcmliZShkc3RfMl9wb3AkY3JpbWVUb3RhbCkKZHN0XzJfc3RhdHNSYXRlIDwtIGRlc2NyaWJlKGRzdF8yX3BvcCRjcmltZVJhdGUpCgpkc3RfMl9zdGF0c1RvdGFsCmRzdF8yX3N0YXRzUmF0ZQpgYGAKCgpgYGB7ciBHZW5lcmF0ZSBEaXN0cmljdCA1IERlbnNpdHkgTWFwc30KZHN0NV9yYXRlTWFwIDwtIHRtX3NoYXBlKGRzdDVfdGlsZXMpICsKICB0bV9yZ2IoKSArCiAgdG1fc2hhcGUoZHN0XzVfcG9wKSArCiAgdG1fcG9seWdvbnMoY29sID0gImNyaW1lUmF0ZSIsCiAgICAgICAgICAgICAgcGFsZXR0ZSA9ICJCdVB1IiwKICAgICAgICAgICAgICBzdHlsZSA9ICJqZW5rcyIsCiAgICAgICAgICAgICAgdGl0bGUgPSAiQ3JpbWVzIHBlciAxLDAwMCBSZXNpZGVudHMiKSArCiAgdG1fdGV4dCgibmVpZ2hib3Job29kIiwgc2hhZG93PVRSVUUpICsKICB0bV9sYXlvdXQoCiAgICBtYWluLnRpdGxlID0gIkRpc3RyaWN0IDUgQ3JpbWUgUmF0ZXMgLSBBdWd1c3QgMjAxOSIsCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLmJnLmNvbG9yID0gIndoaXRlIiwgCiAgICBsZWdlbmQuZnJhbWU9VFJVRSwKICAgIGxlZ2VuZC5vdXRzaWRlID0gVFJVRSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoInJpZ2h0IiwgImJvdHRvbSIpKSAKCmRzdDVfcmF0ZU1hcApgYGAKYGBge3J9CmRzdF81X3N0YXRzVG90YWwgPC0gZGVzY3JpYmUoZHN0XzVfcG9wJGNyaW1lVG90YWwpCmRzdF81X3N0YXRzUmF0ZSA8LSBkZXNjcmliZShkc3RfNV9wb3AkY3JpbWVSYXRlKQoKZHN0XzVfc3RhdHNUb3RhbApkc3RfNV9zdGF0c1JhdGUKYGBgCgoKIyMjIFNhdmUgTWFwcwoKYGBge3IgU2F2ZSBGUFNFIE1hcHMsIGVjaG8gPSBGQUxTRSwgaW5jbHVkZSA9IEZBTFNFfQp0bWFwX3NhdmUoZnBzZV90b3RhbF90bSwgZmlsZSA9IGhlcmUoInJlc3VsdHMvZnBzZS8yMDE5L2F1Z3VzdC9mcHNlX3RvdGFsX2NyaW1lcy5qcGVnIiksIGRwaSA9IDUwMCkKdG1hcF9zYXZlKGZwc2VfZG5fdG0sIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2Zwc2UvMjAxOS9hdWd1c3QvZnBzZV9kYXlfbmlnaHQuanBlZyIpLCBkcGkgPSA1MDApCnRtYXBfc2F2ZShmcHNlX3ZsbnRfdG0sIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2Zwc2UvMjAxOS9hdWd1c3QvZnBzZV92bG50LmpwZWciKSwgZHBpID0gNTAwKQp0bWFwX3NhdmUoZnBzZV9kZW5fdG0sIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2Zwc2UvMjAxOS9hdWd1c3QvZnBzZV9kZW5zaXR5LmpwZWciKSwgZHBpID0gNTAwKQp0bWFwX3NhdmUoZnBzZV9ncm92ZV90bSwgZmlsZSA9IGhlcmUoInJlc3VsdHMvZnBzZS8yMDE5L2F1Z3VzdC9mcHNlX2dyb3ZlLmpwZWciKSwgZHBpID0gNTAwKQpgYGAKCmBgYHtyIFNhdmUgQ1dFIE1hcHMsIGVjaG8gPSBGQUxTRSwgaW5jbHVkZSA9IEZBTFNFfQp0bWFwX3NhdmUoY3dlX3RvdGFsX3RtLCBmaWxlID0gaGVyZSgicmVzdWx0cy9jd2UvMjAxOS9hdWd1c3QvY3dlX3RvdGFsX2NyaW1lcy5qcGVnIiksIGRwaSA9IDUwMCkKdG1hcF9zYXZlKGN3ZV9kbl90bSwgZmlsZSA9IGhlcmUoInJlc3VsdHMvY3dlLzIwMTkvYXVndXN0L2N3ZV9kYXlfbmlnaHQuanBlZyIpLCBkcGkgPSA1MDApCnRtYXBfc2F2ZShjd2VfdmxudF90bSwgZmlsZSA9IGhlcmUoInJlc3VsdHMvY3dlLzIwMTkvYXVndXN0L2N3ZV92bG50LmpwZWciKSwgZHBpID0gNTAwKQp0bWFwX3NhdmUoY3dlX2Rlbl90bSwgZmlsZSA9IGhlcmUoInJlc3VsdHMvY3dlLzIwMTkvYXVndXN0L2N3ZV9kZW4uanBlZyIpLCBkcGkgPSA1MDApCnRtYXBfc2F2ZShjd2VfbWNfdG0sIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2N3ZS8yMDE5L2F1Z3VzdC9jd2VfbWMuanBlZyIpLCBkcGkgPSA1MDApCnRtYXBfc2F2ZShjd2VfY3R4X3RtLCBmaWxlID0gaGVyZSgicmVzdWx0cy9jd2UvMjAxOS9hdWd1c3QvY3dlX2N0eC5qcGVnIiksIGRwaSA9IDUwMCkKYGBgCgpgYGB7ciBTYXZlIEJPVCBNYXAsIGVjaG8gPSBGQUxTRSwgaW5jbHVkZSA9IEZBTFNFfQp0bWFwX3NhdmUoYm90X3RvdGFsX3RtLCBmaWxlID0gaGVyZSgicmVzdWx0cy9ib3QvMjAxOS9ib3RfYXVnX3RvdGFsLmpwZWciKSwgZHBpID0gNTAwKQpgYGAKCmBgYHtyIFNhdmUgRGlzdHJpY3QgRGVuc2l0eSBNYXBzLCBlY2hvID0gRkFMU0UsIGluY2x1ZGUgPSBGQUxTRX0KdG1hcF9zYXZlKGRzdDJfcmF0ZU1hcCwgZmlsZSA9IGhlcmUoInJlc3VsdHMvZGlzdHJpY3QtMi8yMDE5L2RzdDJfYXVnX3JhdGVzLmpwZWciKSwgZHBpID0gNTAwKQp0bWFwX3NhdmUoZHN0NV9yYXRlTWFwLCBmaWxlID0gaGVyZSgicmVzdWx0cy9kaXN0cmljdC01LzIwMTkvZHN0NV9hdWdfcmF0ZXMuanBlZyIpLCBkcGkgPSA1MDApCmBgYAoKIyMjIENsZWFuIFdvcmtzcGFjZSAKCmBgYHtyIFJlbW92ZSBPYmplY3RzIGZyb20gRW52aXJvbm1lbnR9CnJtKGZwc2VfdG90YWxfdG0sIGZwc2VfZG5fdG0sIGZwc2VfdmxudF90bSwgZnBzZV9kZW5fdG0sIGZwc2VfZ3JvdmVfdG0sIGN3ZV90b3RhbF90bSwgY3dlX2RuX3RtLCBjd2VfdmxudF90bSwgY3dlX2Rlbl90bSwgY3dlX21jX3RtLCBjd2VfY3R4X3RtLCBib3RfdG90YWxfdG0sIGZwc2VfdGlsZXMsIGN3ZV90aWxlcywgYm90X3RpbGVzLCBtY190aWxlcywgY3R4X3RpbGVzLCBncnZfdGlsZXMsIGRzdF8yLCBkc3RfNSwgZHN0Ml90aWxlcywgZHN0NV90aWxlcykKYGBgCgojIyBUYWJsZXMgCgojIyMgRlBTRSBUYWJsZXMgCgpgYGB7ciBGUFNFIFRhYmxlc30KdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM5KSAlPiUgCiAgZ3JvdXBfYnkoY3JpbWVDYXROYW1lKSAlPiUgCiAgY291bnQoKSAlPiUgCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJQYXJ0IDEgQ3JpbWVzIiA9IGNyaW1lQ2F0TmFtZSkgLT4gZnBzZV9jcmltZUNhdAoKdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM5KSAlPiUgCiAgZ3JvdXBfYnkod2Vla2RheSkgJT4lIAogIGNvdW50KCkgJT4lCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJEYXkgb2YgdGhlIFdlZWsiID0gd2Vla2RheSkgLT4gZnBzZV93ZWVrRGF5Cgp0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICBncm91cF9ieSh2aW9sZW50KSAlPiUgCiAgY291bnQoKSAlPiUKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAlPiUKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbiwgIkNyaW1lcyBBZ2FpbnN0IFBlcnNvbnMiID0gdmlvbGVudCkgLT4gZnBzZV92aW9sZW50CgoKdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM5KSAlPiUgCiAgZ3JvdXBfYnkoZGF5TmlnaHQpICU+JSAKICBjb3VudCgpICU+JQogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiVGltZSBvZiBEYXkiID0gZGF5TmlnaHQpIC0+IGZwc2VfZGF5TmlnaHQKCnRpZHlUb3RhbENyaW1lczE4ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM5KSAlPiUgCiAgZ3JvdXBfYnkobW9udGhWYXIpICU+JSAKICBjb3VudChjcmltZUNhdE5hbWUpICU+JSAKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbikgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBtb250aFZhciwgdmFsdWVzX2Zyb20gPSAiTnVtYmVyIG9mIENyaW1lcyIpICU+JSAKICByZXBsYWNlKC4sIGlzLm5hKC4pLCAwKSAlPiUgCiAgcmVuYW1lKC4sICJQYXJ0IDEgQ3JpbWVzIiA9IGNyaW1lQ2F0TmFtZSwgCiAgICAgICAgICJKYW51YXJ5IiA9ICIwMSIsCiAgICAgICAgICJGZWJydWFyeSIgPSAiMDIiLAogICAgICAgICAiTWFyY2giID0gIjAzIiwKICAgICAgICAgIkFwcmlsIiA9ICIwNCIsCiAgICAgICAgICJNYXkiID0gIjA1IiwKICAgICAgICAgIkp1bmUiID0gIjA2IiwKICAgICAgICAgIkp1bHkiID0gIjA3IiwKICAgICAgICAgIkF1Z3VzdCIgPSAiMDgiLAogICAgICAgICAiU2VwdGVtYmVyIiA9ICIwOSIsCiAgICAgICAgICJPY3RvYmVyIiA9ICIxMCIsCiAgICAgICAgICJOb3ZlbWJlciIgPSAiMTEiLAogICAgICAgICAiRGVjZW1iZXIiID0gIjEyIikgJT4lIAogIGFkb3JuX3RvdGFscyguLCAiY29sIiwgbmFtZSA9ICJUb3RhbCIpICU+JSAKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAtPiBmcHNlXzIwMTgKCnRpZHlUb3RhbENyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM5KSAlPiUgCiAgZ3JvdXBfYnkobW9udGhWYXIpICU+JSAKICBjb3VudChjcmltZUNhdE5hbWUpICU+JSAKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbikgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBtb250aFZhciwgdmFsdWVzX2Zyb20gPSAiTnVtYmVyIG9mIENyaW1lcyIpICU+JSAKICByZXBsYWNlKC4sIGlzLm5hKC4pLCAwKSAlPiUgCiAgcmVuYW1lKC4sICJQYXJ0IDEgQ3JpbWVzIiA9IGNyaW1lQ2F0TmFtZSwgCiAgICAgICAgICJKYW51YXJ5IiA9ICIwMSIsCiAgICAgICAgICJGZWJydWFyeSIgPSAiMDIiLAogICAgICAgICAiTWFyY2giID0gIjAzIiwKICAgICAgICAgIkFwcmlsIiA9ICIwNCIsCiAgICAgICAgICJNYXkiID0gIjA1IiwKICAgICAgICAgIkp1bmUiID0gIjA2IiwKICAgICAgICAgIkp1bHkiID0gIjA3IiwKICAgICAgICAgIkF1Z3VzdCIgPSAiMDgiKSAlPiUgCiAgYWRvcm5fdG90YWxzKC4sICJjb2wiLCBuYW1lID0gIlRvdGFsIikgJT4lIAogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpIC0+IGZwc2VfMjAxOQoKZnBzZV9sYXJjZW5pZXMgPC0gdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM5KSAlPiUgCiAgZmlsdGVyKC4sIGNyaW1lQ2F0TnVtID09IDYpCgp3cml0ZS5jc3YoZnBzZV9sYXJjZW5pZXMsIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2Zwc2UvMjAxOS9hdWd1c3QvbGFyY2VuaWVzLmNzdiIpKQoKZnBzZV9sYXJjZW5pZXMgJT4lIAogIGdyb3VwX2J5KHdlZWtkYXkpICU+JSAKICBjb3VudCgpICU+JQogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiRGF5IG9mIHRoZSBXZWVrIiA9IHdlZWtkYXkpIC0+IGZwc2VfbGFyY2VuaWVzX3dlZWtEYXkKCmZwc2VfbGFyY2VuaWVzICU+JSAKICBncm91cF9ieShkYXlOaWdodCkgJT4lIAogIGNvdW50KCkgJT4lCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJUaW1lIG9mIERheSIgPSBkYXlOaWdodCkgLT4gZnBzZV9sYXJjZW5pZXNfZGF5TmlnaHQKYGBgCgoKYGBge3J9CmthYmxlKGZwc2VfY3JpbWVDYXQpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiZnBzZV9jcmltQ2F0LmpwZWciKQoKa2FibGUoZnBzZV93ZWVrRGF5KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImZwc2Vfd2Vla0RheS5qcGVnIikKCmthYmxlKGZwc2VfdmlvbGVudCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJmcHNlX3Zpb2xlbnQuanBlZyIpCgprYWJsZShmcHNlX2RheU5pZ2h0KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImZwc2VfZGF5TmlnaHQuanBlZyIpCgprYWJsZShmcHNlXzIwMTgpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiZnBzZV8yMDE4LmpwZWciKQoKa2FibGUoZnBzZV8yMDE5KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImZwc2VfMjAxOS5qcGVnIikKCmthYmxlKGZwc2VfbGFyY2VuaWVzX3dlZWtEYXkpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiZnBzZV9sYXJjZW5pZXNfd2Vla0RheS5qcGVnIikKCmthYmxlKGZwc2VfbGFyY2VuaWVzX2RheU5pZ2h0KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImZwc2VfbGFyY2VuaWVzX2RheU5pZ2h0LmpwZWciKQpgYGAKCgojIyMgQ1dFIFRhYmxlcyAKCmBgYHtyIENXRSBUYWJsZXN9CnRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOCkgJT4lIAogIGdyb3VwX2J5KGNyaW1lQ2F0TmFtZSkgJT4lIAogIGNvdW50KCkgJT4lIAogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiUGFydCAxIENyaW1lcyIgPSBjcmltZUNhdE5hbWUpIC0+IGN3ZV9jcmltZUNhdAoKdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM4KSAlPiUgCiAgZ3JvdXBfYnkod2Vla2RheSkgJT4lIAogIGNvdW50KCkgJT4lCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJEYXkgb2YgdGhlIFdlZWsiID0gd2Vla2RheSkgLT4gY3dlX3dlZWtEYXkKCnRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOCkgJT4lIAogIGdyb3VwX2J5KHZpb2xlbnQpICU+JSAKICBjb3VudCgpICU+JQogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiQ3JpbWVzIEFnYWluc3QgUGVyc29ucyIgPSB2aW9sZW50KSAtPiBjd2VfdmlvbGVudAoKCnRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOCkgJT4lIAogIGdyb3VwX2J5KGRheU5pZ2h0KSAlPiUgCiAgY291bnQoKSAlPiUKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAlPiUKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbiwgIlRpbWUgb2YgRGF5IiA9IGRheU5pZ2h0KSAtPiBjd2VfZGF5TmlnaHQKCnRpZHlUb3RhbENyaW1lczE4ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM4KSAlPiUgCiAgZ3JvdXBfYnkobW9udGhWYXIpICU+JSAKICBjb3VudChjcmltZUNhdE5hbWUpICU+JSAKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbikgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBtb250aFZhciwgdmFsdWVzX2Zyb20gPSAiTnVtYmVyIG9mIENyaW1lcyIpICU+JSAKICByZXBsYWNlKC4sIGlzLm5hKC4pLCAwKSAlPiUgCiAgcmVuYW1lKC4sICJQYXJ0IDEgQ3JpbWVzIiA9IGNyaW1lQ2F0TmFtZSwgCiAgICAgICAgICJKYW51YXJ5IiA9ICIwMSIsCiAgICAgICAgICJGZWJydWFyeSIgPSAiMDIiLAogICAgICAgICAiTWFyY2giID0gIjAzIiwKICAgICAgICAgIkFwcmlsIiA9ICIwNCIsCiAgICAgICAgICJNYXkiID0gIjA1IiwKICAgICAgICAgIkp1bmUiID0gIjA2IiwKICAgICAgICAgIkp1bHkiID0gIjA3IiwKICAgICAgICAgIkF1Z3VzdCIgPSAiMDgiLAogICAgICAgICAiU2VwdGVtYmVyIiA9ICIwOSIsCiAgICAgICAgICJPY3RvYmVyIiA9ICIxMCIsCiAgICAgICAgICJOb3ZlbWJlciIgPSAiMTEiLAogICAgICAgICAiRGVjZW1iZXIiID0gIjEyIikgJT4lIAogIGFkb3JuX3RvdGFscyguLCAiY29sIiwgbmFtZSA9ICJUb3RhbCIpICU+JSAKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAtPiBjd2VfMjAxOAoKdGlkeVRvdGFsQ3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzgpICU+JSAKICBncm91cF9ieShtb250aFZhcikgJT4lIAogIGNvdW50KGNyaW1lQ2F0TmFtZSkgJT4lIAogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IG1vbnRoVmFyLCB2YWx1ZXNfZnJvbSA9ICJOdW1iZXIgb2YgQ3JpbWVzIikgJT4lIAogIHJlcGxhY2UoLiwgaXMubmEoLiksIDApICU+JSAKICByZW5hbWUoLiwgIlBhcnQgMSBDcmltZXMiID0gY3JpbWVDYXROYW1lLCAKICAgICAgICAgIkphbnVhcnkiID0gIjAxIiwKICAgICAgICAgIkZlYnJ1YXJ5IiA9ICIwMiIsCiAgICAgICAgICJNYXJjaCIgPSAiMDMiLAogICAgICAgICAiQXByaWwiID0gIjA0IiwKICAgICAgICAgIk1heSIgPSAiMDUiLAogICAgICAgICAiSnVuZSIgPSAiMDYiLAogICAgICAgICAiSnVseSIgPSAiMDciLAogICAgICAgICAiQXVndXN0IiA9ICIwOCIpICU+JSAKICBhZG9ybl90b3RhbHMoLiwgImNvbCIsIG5hbWUgPSAiVG90YWwiKSAlPiUgCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgLT4gY3dlXzIwMTkKCmN3ZV9sYXJjZW5pZXMgPC0gdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM4KSAlPiUgCiAgZmlsdGVyKC4sIGNyaW1lQ2F0TnVtID09IDYpIAoKd3JpdGUuY3N2KGN3ZV9sYXJjZW5pZXMsIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2N3ZS8yMDE5L2F1Z3VzdC9sYXJjZW5pZXMuY3N2IikpCgpjd2VfbGFyY2VuaWVzICU+JSAKICBncm91cF9ieSh3ZWVrZGF5KSAlPiUgCiAgY291bnQoKSAlPiUKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAlPiUKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbiwgIkRheSBvZiB0aGUgV2VlayIgPSB3ZWVrZGF5KSAtPiBjd2VfbGFyY2VuaWVzX3dlZWtEYXkKCmN3ZV9sYXJjZW5pZXMgJT4lIAogIGdyb3VwX2J5KGRheU5pZ2h0KSAlPiUgCiAgY291bnQoKSAlPiUKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAlPiUKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbiwgIlRpbWUgb2YgRGF5IiA9IGRheU5pZ2h0KSAtPiBjd2VfbGFyY2VuaWVzX2RheU5pZ2h0CmBgYAoKCmBgYHtyfQprYWJsZShjd2VfY3JpbWVDYXQpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiY3dlX2NyaW1DYXQuanBlZyIpCgprYWJsZShjd2Vfd2Vla0RheSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJjd2Vfd2Vla0RheS5qcGVnIikKCmthYmxlKGN3ZV92aW9sZW50KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImN3ZV92aW9sZW50LmpwZWciKQoKa2FibGUoY3dlX2RheU5pZ2h0KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImN3ZV9kYXlOaWdodC5qcGVnIikKCmthYmxlKGN3ZV8yMDE4KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImN3ZV8yMDE4LmpwZWciKQoKa2FibGUoY3dlXzIwMTkpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiY3dlXzIwMTkuanBlZyIpCgprYWJsZShjd2VfbGFyY2VuaWVzX3dlZWtEYXkpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiY3dlX2xhcmNlbmllc193ZWVrRGF5LmpwZWciKQoKa2FibGUoY3dlX2xhcmNlbmllc19kYXlOaWdodCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJjd2VfbGFyY2VuaWVzX2RheU5pZ2h0LmpwZWciKQpgYGAKCmBgYHtyfQpoZWFkKGZwc2VfMjAxOCkgCndyaXRlLmNzdihmcHNlXzIwMTgsIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2Zwc2UvMjAxOS9hdWd1c3QvZnBzZV8yMDE4LmNzdiIpKQpgYGAKCmBgYHtyfQpoZWFkKGZwc2VfMjAxOSkKd3JpdGUuY3N2KGZwc2VfMjAxOSwgZmlsZSA9IGhlcmUoInJlc3VsdHMvZnBzZS8yMDE5L2F1Z3VzdC9mcHNlXzIwMTkuY3N2IikpCmBgYAoKYGBge3J9CmhlYWQoY3dlXzIwMTgpCndyaXRlLmNzdihjd2VfMjAxOCwgZmlsZSA9IGhlcmUoInJlc3VsdHMvY3dlLzIwMTkvYXVndXN0L2N3ZV8yMDE4LmNzdiIpKQpgYGAKCmBgYHtyfQpoZWFkKGN3ZV8yMDE5KQp3cml0ZS5jc3YoY3dlXzIwMTksIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2N3ZS8yMDE5L2F1Z3VzdC9jd2VfMjAxOS5jc3YiKSkKYGBgCgojIyMgQm90YW5pY2FsIEhlaWdodHMKCmBgYHtyIEJPVCBUYWJsZXN9CnRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAyOCkgJT4lIAogIGdyb3VwX2J5KGNyaW1lQ2F0TmFtZSkgJT4lIAogIGNvdW50KCkgJT4lIAogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiUGFydCAxIENyaW1lcyIgPSBjcmltZUNhdE5hbWUpIC0+IGJvdF9jcmltZUNhdAoKdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDI4KSAlPiUgCiAgZ3JvdXBfYnkod2Vla2RheSkgJT4lIAogIGNvdW50KCkgJT4lCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgJT4lCiAgcmVuYW1lKC4sICJOdW1iZXIgb2YgQ3JpbWVzIiA9IG4sICJEYXkgb2YgdGhlIFdlZWsiID0gd2Vla2RheSkgLT4gYm90X3dlZWtEYXkKCnRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAyOCkgJT4lIAogIGdyb3VwX2J5KHZpb2xlbnQpICU+JSAKICBjb3VudCgpICU+JQogIGFkb3JuX3RvdGFscyguLCAicm93IiwgbmFtZSA9ICJUb3RhbCIpICU+JQogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuLCAiQ3JpbWVzIEFnYWluc3QgUGVyc29ucyIgPSB2aW9sZW50KSAtPiBib3RfdmlvbGVudAoKCnRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAyOCkgJT4lIAogIGdyb3VwX2J5KGRheU5pZ2h0KSAlPiUgCiAgY291bnQoKSAlPiUKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAlPiUKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbiwgIlRpbWUgb2YgRGF5IiA9IGRheU5pZ2h0KSAtPiBib3RfZGF5TmlnaHQKCnRpZHlUb3RhbENyaW1lczE4ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDI4KSAlPiUgCiAgZ3JvdXBfYnkobW9udGhWYXIpICU+JSAKICBjb3VudChjcmltZUNhdE5hbWUpICU+JSAKICByZW5hbWUoLiwgIk51bWJlciBvZiBDcmltZXMiID0gbikgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBtb250aFZhciwgdmFsdWVzX2Zyb20gPSAiTnVtYmVyIG9mIENyaW1lcyIpICU+JSAKICByZXBsYWNlKC4sIGlzLm5hKC4pLCAwKSAlPiUgCiAgcmVuYW1lKC4sICJQYXJ0IDEgQ3JpbWVzIiA9IGNyaW1lQ2F0TmFtZSwgCiAgICAgICAgICJKYW51YXJ5IiA9ICIwMSIsCiAgICAgICAgICJGZWJydWFyeSIgPSAiMDIiLAogICAgICAgICAiTWFyY2giID0gIjAzIiwKICAgICAgICAgIkFwcmlsIiA9ICIwNCIsCiAgICAgICAgICJNYXkiID0gIjA1IiwKICAgICAgICAgIkp1bmUiID0gIjA2IiwKICAgICAgICAgIkp1bHkiID0gIjA3IiwKICAgICAgICAgIkF1Z3VzdCIgPSAiMDgiLAogICAgICAgICAiU2VwdGVtYmVyIiA9ICIwOSIsCiAgICAgICAgICJPY3RvYmVyIiA9ICIxMCIsCiAgICAgICAgICJOb3ZlbWJlciIgPSAiMTEiLAogICAgICAgICAiRGVjZW1iZXIiID0gIjEyIikgJT4lIAogIGFkb3JuX3RvdGFscyguLCAiY29sIiwgbmFtZSA9ICJUb3RhbCIpICU+JSAKICBhZG9ybl90b3RhbHMoLiwgInJvdyIsIG5hbWUgPSAiVG90YWwiKSAtPiBib3RfMjAxOAp3cml0ZS5jc3YoYm90XzIwMTgsIGZpbGUgPSBoZXJlKCJyZXN1bHRzL2JvdC8yMDE5L2JvdF8yMDE4LmNzdiIpKQoKdGlkeVRvdGFsQ3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMjgpICU+JSAKICBncm91cF9ieShtb250aFZhcikgJT4lIAogIGNvdW50KGNyaW1lQ2F0TmFtZSkgJT4lIAogIHJlbmFtZSguLCAiTnVtYmVyIG9mIENyaW1lcyIgPSBuKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IG1vbnRoVmFyLCB2YWx1ZXNfZnJvbSA9ICJOdW1iZXIgb2YgQ3JpbWVzIikgJT4lIAogIHJlcGxhY2UoLiwgaXMubmEoLiksIDApICU+JSAKICByZW5hbWUoLiwgIlBhcnQgMSBDcmltZXMiID0gY3JpbWVDYXROYW1lLCAKICAgICAgICAgIkphbnVhcnkiID0gIjAxIiwKICAgICAgICAgIkZlYnJ1YXJ5IiA9ICIwMiIsCiAgICAgICAgICJNYXJjaCIgPSAiMDMiLAogICAgICAgICAiQXByaWwiID0gIjA0IiwKICAgICAgICAgIk1heSIgPSAiMDUiLAogICAgICAgICAiSnVuZSIgPSAiMDYiLAogICAgICAgICAiSnVseSIgPSAiMDciLAogICAgICAgICAiQXVndXN0IiA9ICIwOCIpICU+JSAKICBhZG9ybl90b3RhbHMoLiwgImNvbCIsIG5hbWUgPSAiVG90YWwiKSAlPiUgCiAgYWRvcm5fdG90YWxzKC4sICJyb3ciLCBuYW1lID0gIlRvdGFsIikgLT4gYm90XzIwMTkKd3JpdGUuY3N2KGJvdF8yMDE5LCBmaWxlID0gaGVyZSgicmVzdWx0cy9ib3QvMjAxOS9ib3RfMjAxOS5jc3YiKSkKYGBgCgpgYGB7cn0Ka2FibGUoYm90X2NyaW1lQ2F0KSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAiY2VudGVyIikgJT4lIAogIHNhdmVfa2FibGUoImJvdF9jcmltQ2F0LmpwZWciKQoKa2FibGUoYm90X3dlZWtEYXkpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGLCBwb3NpdGlvbiA9ICJjZW50ZXIiKSAlPiUgCiAgc2F2ZV9rYWJsZSgiYm90X3dlZWtEYXkuanBlZyIpCgprYWJsZShib3RfdmlvbGVudCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJib3RfdmlvbGVudC5qcGVnIikKCmthYmxlKGJvdF9kYXlOaWdodCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEYsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JSAKICBzYXZlX2thYmxlKCJib3RfZGF5TmlnaHQuanBlZyIpCmBgYAoKCiMjIEdyYXBocy9DaGFydHMKCm5lZWQgdG8gY2hhbmdlIGZpbGUgc2F2ZSBsb2NhdGlvbnMKCiMjIyBGUFNFIEdyYXBocyAKCmBgYHtyIEZQU0UgQ3JpbWUgYnkgV2Vla2RheSAtIEdyYXBofQp0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICBncm91cF9ieSh3ZWVrZGF5KSAlPiUgCiAgY291bnQoKSAlPiUKICBnZ3Bsb3QoLiwgYWVzKHg9d2Vla2RheSwgeT1uLCBncm91cD0xKSkgKwogICAgZ2VvbV9saW5lKGNvbG9yPSJibHVlIikgKwogICAgZ2VvbV9wb2ludCgpICsgCiAgICB4bGFiKCJEYXkgb2YgV2VlayIpICsgeWxhYigiVG90YWwgQ3JpbWVzIikgKwogICAgZ2d0aXRsZSgiRlBTRSBUb3RhbCBDcmltZXMgYnkgRGF5cyBvZiB0aGUgV2VlayIpCgpnZ3NhdmUoaGVyZSgicmVzdWx0cy9ncmFwaHMvZnBzZV9jcmltZV93ZWVrZGF5LmpwZWciKSwgZHBpID0gMzAwKQpgYGAKCmBgYHtyIEZQU0UgQ3JpbWUgYnkgQ2F0ZWdvcnkgV2Vla2RheSAtIEdyYXBofQp0aWR5Q3JpbWVzMTkgJT4lIAogIGZpbHRlciguLCBuZWlnaGJvcmhvb2QgPT0gMzkpICU+JSAKICBncm91cF9ieShjcmltZUNhdE5hbWUpICU+JQogIGdncGxvdCguLCBhZXMod2Vla2RheSkpICsKICAgIGdlb21fYmFyKGFlcyhmaWxsID0gY3JpbWVDYXROYW1lKSwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoKSkgKwogICAgeGxhYigiRGF5IG9mIFdlZWsiKSArIHlsYWIoIlRvdGFsIENyaW1lcyIpICsKICAgIGdndGl0bGUoIkZQU0UgQ3JpbWVzIGJ5IERheSAmIENhdGVnb3J5IikgKyAKICAgIGxhYnMoZmlsbCA9ICJQYXJ0IDEgQ3JpbWVzIikgKwogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpCgpnZ3NhdmUoaGVyZSgicmVzdWx0cy9ncmFwaHMvZnBzZV9jcmltZUNhdF93ZWVrZGF5LmpwZWciKSwgZHBpID0gMzAwKQpgYGAKCgoKYGBge3IgRlBTRSBDcmltZSBieSBUaW1lIG9mIERheSB9CnRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAzOSkgJT4lIAogIGdyb3VwX2J5KGRheU5pZ2h0KSAlPiUKICBjb3VudCgpICU+JSAKICBnZ3Bsb3QoLiwgYWVzKHg9ZGF5TmlnaHQsIHk9biwgZmlsbCA9IGRheU5pZ2h0KSkgKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSgpLCBjb2xvdXI9ImJsYWNrIikgKwogICAgeGxhYigiVGltZSBvZiBEYXkiKSArIHlsYWIoIlRvdGFsIENyaW1lcyIpICsKICAgIGdndGl0bGUoIkZQU0UgQ3JpbWVzIGJ5IFRpbWUgb2YgRGF5IikgKyAKICAgIGxhYnMoZmlsbCA9ICJUaW1lIikKCmdnc2F2ZShoZXJlKCJyZXN1bHRzL2dyYXBocy9mcHNlX2NyaW1lX3RpbWVEYXkuanBlZyIpLCBkcGkgPSAzMDApCmBgYAoKCiMjIyBDV0UgR3JhcGhzIAoKYGBge3IgQ1dFIENyaW1lIGJ5IFdlZWtkYXkgLSBHcmFwaH0KdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM4KSAlPiUgCiAgZ3JvdXBfYnkod2Vla2RheSkgJT4lIAogIGNvdW50KCkgJT4lCiAgZ2dwbG90KC4sIGFlcyh4PXdlZWtkYXksIHk9biwgZ3JvdXA9MSkpICsKICAgIGdlb21fbGluZShjb2xvcj0iYmx1ZSIpICsKICAgIGdlb21fcG9pbnQoKSArIAogICAgeGxhYigiRGF5IG9mIFdlZWsiKSArIHlsYWIoIlRvdGFsIENyaW1lcyIpICsKICAgIGdndGl0bGUoIkNXRSBUb3RhbCBDcmltZXMgYnkgRGF5cyBvZiB0aGUgV2VlayIpCgpnZ3NhdmUoaGVyZSgicmVzdWx0cy9ncmFwaHMvY3dlX2NyaW1lX3dlZWtkYXkuanBlZyIpLCBkcGkgPSAzMDApCmBgYAoKYGBge3IgQ1dFIENyaW1lIGJ5IENhdGVnb3J5IFdlZWtkYXkgLSBHcmFwaH0KdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM4KSAlPiUgCiAgZ3JvdXBfYnkoY3JpbWVDYXROYW1lKSAlPiUKICBnZ3Bsb3QoLiwgYWVzKHdlZWtkYXkpKSArCiAgICBnZW9tX2JhcihhZXMoZmlsbCA9IGNyaW1lQ2F0TmFtZSksIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKCkpICsKICAgIHhsYWIoIkRheSBvZiBXZWVrIikgKyB5bGFiKCJUb3RhbCBDcmltZXMiKSArCiAgICBnZ3RpdGxlKCJDV0UgQ3JpbWVzIGJ5IERheSAmIENhdGVnb3J5IikgKyAKICAgIGxhYnMoZmlsbCA9ICJQYXJ0IDEgQ3JpbWVzIikgKwogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpCgpnZ3NhdmUoaGVyZSgicmVzdWx0cy9ncmFwaHMvY3dlX2NyaW1lQ2F0X3dlZWtkYXkuanBlZyIpLCBkcGkgPSAzMDApCgpgYGAKCgoKYGBge3IgQ1dFIENyaW1lIGJ5IFRpbWUgb2YgRGF5IH0KdGlkeUNyaW1lczE5ICU+JSAKICBmaWx0ZXIoLiwgbmVpZ2hib3Job29kID09IDM4KSAlPiUgCiAgZ3JvdXBfYnkoZGF5TmlnaHQpICU+JQogIGNvdW50KCkgJT4lIAogIGdncGxvdCguLCBhZXMoeD1kYXlOaWdodCwgeT1uLCBmaWxsID0gZGF5TmlnaHQpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKCksIGNvbG91cj0iYmxhY2siKSArCiAgICB4bGFiKCJUaW1lIG9mIERheSIpICsgeWxhYigiVG90YWwgQ3JpbWVzIikgKwogICAgZ2d0aXRsZSgiQ1dFIENyaW1lcyBieSBUaW1lIG9mIERheSIpICsgCiAgICBsYWJzKGZpbGwgPSAiVGltZSIpIAoKZ2dzYXZlKGhlcmUoInJlc3VsdHMvZ3JhcGhzL2N3ZV9jcmltZV90aW1lRGF5LmpwZWciKSwgZHBpID0gMzAwKQpgYGAKIyMjIEJPVCAKCmBgYHtyIEJPVCBDcmltZSBieSBXZWVrZGF5IC0gR3JhcGh9CnRpZHlDcmltZXMxOSAlPiUgCiAgZmlsdGVyKC4sIG5laWdoYm9yaG9vZCA9PSAyOCkgJT4lIAogIGdyb3VwX2J5KHdlZWtkYXkpICU+JSAKICBjb3VudCgpICU+JQogIGdncGxvdCguLCBhZXMoeD13ZWVrZGF5LCB5PW4sIGdyb3VwPTEpKSArCiAgICBnZW9tX2xpbmUoY29sb3I9ImJsdWUiKSArCiAgICBnZW9tX3BvaW50KCkgKyAKICAgIHhsYWIoIkRheSBvZiBXZWVrIikgKyB5bGFiKCJUb3RhbCBDcmltZXMiKSArCiAgICBnZ3RpdGxlKCJCT1QgVG90YWwgQ3JpbWVzIGJ5IERheXMgb2YgdGhlIFdlZWsiKQoKZ2dzYXZlKGhlcmUoInJlc3VsdHMvZ3JhcGhzL2JvdF9jcmltZV93ZWVrZGF5LmpwZWciKSwgZHBpID0gMzAwKQpgYGAKCg==